ATmega8 - Menetszám számláló

2015-01-02

 

Csemetém megpróbált rávenni, hogy üzemeljük be a vagy 25 éve a fiókban porosodó orosz villanócsöveimet. Nem kukáztam ki őket időben :(. Ehhez ugye gyujtótrafó kell, amit meg tekercselő géppel lehet előállítani. Na most a tekercselő géphez meg kell egy menetszámláló. Tekercselés közben meg az is előfordul, hogy visszatekerünk valamennyit, szóval tudnia kell visszafelé is számolni. Azután kell tudni nullázni. Az is jó lenne, ha be lehetne valamilyen kezdőértéket állítani, és abból számolna le. Jó lenne, ha nemcsak a menetszámot tudná kijelezni, hanem pontosabb lenne. És főleg jó volna, ha nem kívánna bonyolult mechanikát, mert ugye itthon az asztal sarkán, gépműhely híján... Szóval úgy gondoltam, legegyszerűbb, ha a tekercselő gép csévetest forgató részére fehér rovásokat festek fel, és egy optikai fejjel ezt figyelem. A számláló elektronikáját az LCDT01 adta. Annyiban kellett átalakítani, hogy szükségem volt az INT0 és a PD3(5) lábakra, ezért LCD RS láb átkerült az AVR 4-ről az AVR 9-es lábra, LCD E láb pedig az AVR 5-ről az AVR 10-es lábra. Vállon veregettem magam, mert a programban elegendő volt csupán a két definíciót átírni, tehát tényleg sikerült korábban egész flexibilisen megírnom az LCD kezelését.

Nyilván a feladat, hogy egy LED-del meg kell világítani a forgórészt, és fototranyóval figyelni. Két fototranyóval figyeljük, és a kapcsolásuk sorrendjéből meg lehet állapítani, hogy merre forog a fej. Gépműhely, optika híján azt találtam ki, hogy zsugorcsövet húztam a fototranyókra, rámelegítettem, és így kis csövecskék alakultak ki rajtuk, amivel rá lehet őket irányítani a megvilágított felületre. Pontosabban a mindenünnen jövő fényt lehet leszűkíteni/leárnyékolni. A fej működését azt hiszem ránézésre meg lehet érteni.

Az alábbi képen próba közben látható a fej. A kísérletezéshez egy akkus furó fekete tokmányára ragasztottam négy fehér papírcsíkot. Az élet nem habospite. Problémát okozott, hogy a fejet csak kézben tartottam, és nem csináltam hozzá álványt. Nem mindegy hogy tartjuk, viszonylag pontosan be kell állítani. Kellene még egy kis takarás is, mert például az asztali lámpám fénye be tudott zavarni. Hosszú távon az optikai fejek problémája, hogy ba tudnak porosodni. Szóval ez így nem egy ipari kivitel, de müxik.

Itt látható a teljes áramkör. Nagy fényerejű piros LED-et válasszunk. Lehet infra is, de akkor mi nem látjuk csak a fototranyók. Más fototranyó is jó lehet, a Lomex-ben nemrég ezt lehetett jóárasítva ötösével egybecsomagolva kapni.

A program két megszakítást figyel. Az TIMER0 az belső órajlet kapja meg leosztva, és abból nagyjából 100Hz-es megszakítást képez. Ez szolgál a billentyűzet lekérdezés és a kiírás időzítésére. Az egyik fototranyó INT0-ra van kötve és lefutó élre generál megszakítást. Ekkor a program megnézi, hogy a másik tranyó milyen állapotban van, kapott-e már megvilágítást és ennek megfelelően le/fel számol. Van egy belső irány változó, amit a [*] gombbal állítunk, ennek értékét is figyelembe veszi a számlálás irányában. Igazából nem követtem korrektül végig a jelet, mert akár felcseréljük a két tranyót, megfordítjuk a fejet, vagy átallítjuk a megszakítást lefutóról felfutó élre, vagy nem INT0-t hanem INT1-et figyeljük... akárhol felcserélhetjük. Új elem, hogy a programot több részre bontottam. Külön programba került a kpri(), illetve az LCD kezelő rutinok, így jobban lehet a fő programra koncentrálni.

/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   http://www.tkiraaly.hu
*   Date         -  2015.01.02.
*   Chip         -  Atmel ATmega8 & HD44780
*   Compiler     -  avr-gcc (WinAVR)
*
*   Menetszam szamlalo
*   ATmega8, 2x16 karakteres LCD, 3x4 gombos tasztatura, LED, csipogo, optofej 
*
*   Ez egy olyan szamlalo, amely a forgasiranynak megfeleloen fel/le szamol.
*   Becslesem szerint masodpercenkent legalabb 100 osztast kepes megszamolni.
*   A fejen egy fordulaton belul lehet tobb osztas is (alapertelmezett 4).
*   # -     A billentyuzetrol nullazhato. 
*   1..9 -  A billentyuzetrol beirhato a kezdoerteke. 
*   * -     A billentyuzetrol allithato a szamolas iranya. 
*   
********************************************************************************
*   PonyProg Configuration and Security Bits (bepipalva):
*
*   CKSEL3, CKSEL2, CKSEL1, CKSEL0
*   P       P       -       -       0011  Calibrated Internal RC Oscillator 4MHz
*
*   Calibrated Internal RC Oscillator
*   SUT1  SUT0
*   -     P         Slowly rising power
*   
********************************************************************************
*    LCD:
*    14   LCD D7       - AVR PD7  - 13
*    13   LCD D6       - AVR PD6  - 12
*    12   LCD D5       - AVR PD5  - 11
*    11   LCD D4       - AVR PD4  -  6
*    10   LCD D3
*     9   LCD D2
*     8   LCD D1
*     7   LCD D0
*     6   LCD E        - AVR PB7  - 10
*     5   LCD RW       - GND
*     4   LCD RS       - AVR PB6  -  9
*     3   LCD KONTR    - 10 kOhm trim.
*     2   LCD VDD      - +5V
*     1   LCD VSS      - GND
*     
*    KBD:
*     1 KBD COL1       - AVR PC0  - 23
*     2 KBD COL2       - AVR PC1  - 24
*     3 KBD COL3       - AVR PC2  - 25
*     4 KBD ROW1       - AVR PD7  - 13 - 4K7      
*     5 KBD ROW2       - AVR PD6  - 12 - 4K7      
*     6 KBD ROW3       - AVR PD5  - 11 - 4K7      
*     7 KBD ROW4       - AVR PD4  - 10 - 4K7      
*
*    Soros port:
*     1 VCC
*     2 X
*     3 RX             - AVR RXD  -  2
*     4 TX             - ACR TXD  -  3
*     5 GND
*     
*    Programozo fej:
*     1 RST            - AVR NRES -  1
*     2 X
*     3 SCK            - AVR SCK  - 19
*     4 MISO           - AVR MISO - 18
*     5 MOSI           - AVR MOSI - 17
*     6 GND
*
*    Egyeb:
*     LED              - AVR PB0  - 14
*     Csipogo          - AVR PC3  - 26
*     Osztas erzekeles - AVR INT0 - 4  - opto tranyo 1
*     Irany figyeles   - AVR PD3  - 5  - opto tranyo 2
*
*******************************************************************************/

#define F_CPU                _4MHZ


#include "tkiraaly_atmega8.h"
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "tkiraaly_kpri.c"




// LCD_E - PB7
#define LCD_E_ENABLE         PB7_OUT
#define LCD_E_0              BC( PORTB, 7)
#define LCD_E_1              BS( PORTB, 7)

// LCD_RS - PB6
#define LCD_RS_ENABLE        PB6_OUT
#define LCD_RS_UTASITAS      BC( PORTB, 6)
#define LCD_RS_ADAT          BS( PORTB, 6)

// LCD adat port - PORTD felso 4 bit - KBD sorok is
#define LCD_PORT             PORTD
#define LCD_PORT_ENABLE      DDRD|= 0B11110000
#define LCD_PORT_DISABLE     DDRD&= 0B00001111

#include "tkiraaly_lcd.c"




// LED - PB0
#define LED_ENABLE           PB0_OUT
#define LED_BE               BC( PORTB, 0)
#define LED_KI               BS( PORTB, 0)


// SPEAKER
#define SPK_ENABLE           PC3_OUT
#define SPK_BE               BC( PORTC, 3)
#define SPK_KI               BS( PORTC, 3)

#define OSZTASSZAM           4




U8 kbd( void);                                   // billentyuzet lekerdezese es dekodolasa
U8 kbd_antiprell( U8);                           // billentyuzet perges mentesito
void cmd( U8);                                   // bejovo char ertelmezese




volatile U8 speaker= 0;                          // csipogas hossza msec-ben
volatile U8 ido= 0;                              // ido szamlalasa 10 msec-ben
volatile char osztas= 0;                         // osztas szamlalas
volatile int menet= 0;                           // menet szamlalas
volatile U8 gomb= 0;                             // lenyomott gomb
volatile U8 irany= 0;                            // irany valto



 
ISR( INT0_vect)                                  // kulso megszakitas, szamlalas
{
   if( BTC( PIND, 3) == irany)                   // irany lekerdezese
   {                                             // szamlalas fel
      osztas++;
      if( osztas >= OSZTASSZAM)                           // osztasok szama
      {
         menet++;
         osztas-= OSZTASSZAM;
      }
   }  
   else
   {                                             // szamlalas le
      osztas--;
      if( osztas < 0)
      {
         menet--;
         osztas+= OSZTASSZAM;
      }
   }
}




ISR( TIMER0_OVF_vect)                            // masodpercenkent kb 100*
{
   TCNT0= 255- 40;                               // 10,24 msec - kb 100Hz
   ido++;
   gomb= kbd_antiprell( kbd());                  // billentyuzet lekerdezese
   if( gomb)                                     // ha nyomtak egy gombot
   {
      speaker= 30;                               // billentyu hang
      switch( gomb)                              // parancs feldolgozas
      {
         case '*':                               // irany valtas
                   irany= irany ? 0 : 1;
                   break; 
         case '#':                               // reset
                   menet= 0;
                   osztas= 0;
                   break;
         case '0':
         case '1':
         case '2':
         case '3':
         case '4':
         case '5':
         case '6':
         case '7':
         case '8':
         case '9':
                   if( menet < 3100)             // tuliras ellen
                   {
                      menet= menet* 10;
                      menet+= gomb- 48;
                   }
      }
   }
}




int main( void)
{
   SPK_ENABLE;
   LED_ENABLE;
   LED_BE;
   INT0_FALLING;                                 // megszakitas lefuto elre
   IT_INT0_ENABLE; 
   IT_TIMER0_OVF_ENABLE;
   TCNT0= 255- 40;                               // 10,24 msec - kb 100Hz
   T0_FP_1024;                                   // idoalap 0,256 msec
   IT_ENABLE;
   
   lcd_init4();
   lcd_cls();
   lcd_puts( PSTR( "Menetszamlalo:"));

   for(;;)
   {
      if( speaker)                               // gomb hang 1000 Hz
      {
         speaker--;
         SPK_BE;
         _delay_us( 500);
         SPK_KI;
         _delay_us( 500);
      }
      if( ido > 10)                              // kiiras kb masodpercenkent 10x
      {
         ido-= 10;
         lcd_yx( 1, 0);
         if( irany) lcdre( kpri( PSTR( "Fel: %5d,%1d/%1d"), menet, osztas, OSZTASSZAM));
         else       lcdre( kpri( PSTR( "Le:  %5d,%1d/%1d"), menet, osztas, OSZTASSZAM));
      }
   }
   return 0;
}




U8 kbd( void)                                    // billentyuzet lekerdezese es dekodolasa
{
   U8 c;
   c= 0;
   LCD_PORT_DISABLE;
   LCD_PORT &= 0x0F;                             // LCD es KBD port reszben kozos
   PD7_OUT;                                      // 1. sor
   NOP;                                          // 4MHz-nel 1 NOP-pal mar jo
   if( BTC( PINC, 0)) c= '1';
   if( BTC( PINC, 1)) c= '2';
   if( BTC( PINC, 2)) c= '3';
   LCD_PORT_DISABLE;
   PD6_OUT;                                      // 2. sor
   NOP;
   if( BTC( PINC, 0)) c= '4';
   if( BTC( PINC, 1)) c= '5';
   if( BTC( PINC, 2)) c= '6';
   LCD_PORT_DISABLE;
   PD5_OUT;                                      // 3. sor
   NOP;
   if( BTC( PINC, 0)) c= '7';
   if( BTC( PINC, 1)) c= '8';
   if( BTC( PINC, 2)) c= '9';
   LCD_PORT_DISABLE;
   PD4_OUT;                                      // 4. sor
   NOP;
   if( BTC( PINC, 0)) c= '*';
   if( BTC( PINC, 1)) c= '0';
   if( BTC( PINC, 2)) c= '#';
   LCD_PORT_ENABLE;
   return c;
}




U8 kbd_antiprell( U8 c)                          // billentyuzet perges mentesito
{
   static U8 n= 0;                               // nyomvatartas szamlalasahoz 
   U8 a= 0;                                      // visszadott ertek, default 0
   if( c) n++;                                   // ha van lenyomott gomb, szamlalas
   else n= 0;
   if( n == 10) n= 9;                            // szamlalo max 9
   if( n == 3) a= c;                             // harmadik periodusnal megy a gomb
   return a;
}

Itt a vége, fussatok el vélem (én nem futok), legyetek az én vendégeim, innen letölthetitek a hozzávalókat összecsomagolva.