"Kembali Ke Dasar Elektronika Digital ... "

  • IC Timer 555 yang Multifungsi

    IC timer 555 adalah sirkuit terpadu (chip) yang digunakan dalam berbagai pembangkit timer, pulsa dan aplikasi osilator. Komponen ini digunakan secara luas, berkat kemudahan dalam penggunaan, harga rendah dan stabilitas yang baik

  • Animasi LED Dengan IC 4017

    IC 4017 adalah IC 16-pin CMOS dekade counter dari seri IC CMOS 4000. Sangat berguna jika ingin membuat animasi lampu atau LED secara sederhana seperti led berjalan, tulisan berjalan , counter/timer dan masih banyak kegunaan lainnya

  • Bermain DOT Matrix - LOVEHURT

    Project Sederhana dengan Dot Matrix dan Attiny2313. Bisa menjadi hadiah buat teman atau pacarmu yang ulang tahun dengan tulisan dan animasi yang dapat dibuat sendiri.

  • JAM DIGITAL 6 DIGIT TANPA MICRO FULL CMOS

    Jika anda pencinta IC TTL datau CMOS maka project jam digital ini akan menunjukkan bahwa tidak ada salahnya balik kembali ke dasar elektronika digital , sebab semuanya BISA dibuat dengan teknologi jadul

  • BIKIN PCB SEDERHANA TAPI GA MURAHAN

    Bikin PCB itu ga susah kok..dengan software EAGLE CAD dan teknik sterika kamu dapat membuat PCB untuk berbagai project elektronika mu ...

Tampilkan postingan dengan label attiny2313. Tampilkan semua postingan
Tampilkan postingan dengan label attiny2313. Tampilkan semua postingan

Jumat, 29 Mei 2020

[Belajar Mudah] Love Hurt 2020 - Remake pake Arduino




Lama banget gak utak-atik LED MATRIX padahal barang satu ini favorit saya sejak kuliah 20 tahun yang lalu. Kekaguman saya pada benda ini berawal saat tahun 90an saya sering diminta teman membuat LED susun menjadi tulisan tertentu dan kemudian digabung dengan IC 4017 agar menjadi efek gerak kedip kanan kiri, sayangnya karakter yg dibentuk gak bisa diubah. Dan saat saya kuliah ketemu dot matrix yang gak lain led disusun yang bisa diubah ubah tampilannya sesuai keinginan. Bahkan ingatan saya masih clink pada tahun 1998 di atas atap kampus Elektro ITS terpampang text berjalan dari Bohlam yg disusun menjadi seperti LED matrix berukuran super besar. 


Tuh saya masih inget bikin generator susunan led ke bit / hex yang nantinya dimasukkan ke script atmel studio. Dulu saya pake IC legendaris ATTINY 2313 dan banyak yang belajar dari modul pembelajaran (yang saya jual paketan) dimana praktek terakhirnya bikin teks berjalan pada satu marix yang bisa dibaca disini. Kini sudah tahun 2020 saya ingin membagi ilmu nya kembali dengan format lebih jaman now menggunakan Arduino. Lanjut kumpulin bahan-bahannya yuk...


Bahan-bahan dapat disesuaikan dengan yang ada dirumah aja jangan kaku sampe harus beli (walau murah tinggal klik olshop). Rangkaian nya sangat simple karena akan menggunakan pin I/O nomer 2-8 sebagai BARIS dan pin 9-13 sebagai KOLOM dari led matrix. Sebaiknya jika bingung prinsip penyalaan LED MATRIX bisa dibaca dulu dasarnya disini.



Karena Arduino Pro Mini yg saya gunakan memakai header cowok maka sangat simple menyambungkannya  ke Led Matrix dengan menggunakan kabel jumper cewek ke cewek. Tinggal colok seperti gambar dibawah. Kalau pake arduino jenis lain tinggal sesuaikan saja.


Mari kita bahas scriptnya secara mendalam..jangan sampe pusing ya ! Pegangan kalau kepala sudah muncul bintang nya..hehehe


- Penyusunan Karakter di Memori


const byte love1[5] =
{
0b0011110,
0b0100001,
0b1000010,
0b0100001,
0b0011110

};

const byte love2[5] =
{
0b0001100,
0b0010010,
0b0100100,
0b0010010,
0b0001100

};





Untuk menyusun karakter diatas anda butuh mengunduh software TextToBit yang saya kerasikan disini. Jadi saya ingin membuat animasi jantung berdenyut dengan 2 frame karakter yang dinyalakan bergantian (kalau mau banyak ya lebih keren juga). Jadi prinsipnya menyusun BIT sedemikian rupa agar karakter terwakili pada led dengan kombinasi 7 output BARIS (HIGH) vs 5 output KOLOM (LOW). Perhatikan gambar berikut ya ...


Dari gambar dapat dibayangkan bahwa BIT biner pada array (BARIS)  diatas menunjukkan  nilai 1 berarti LED NYALA dan sebaliknya. Selanjutnya akan di scanning KOLOM nya satu persatu secara cepat dan mata melihat sebagai satu gambar utuh. Karena Matrix yg kita gunakan 7x5 maka cukup menggunakan 7 bit saja per baris. 


- Inisialisasi PIN I/O

#define BARIS1 2
#define BARIS2 3
#define BARIS3 4
#define BARIS4 5
#define BARIS5 6
#define BARIS6 7
#define BARIS7 8
#define KOLOM1 9
#define KOLOM2 10
#define KOLOM3 11
#define KOLOM4 12
#define KOLOM5 13


byte kolomnya[5]= {KOLOM1,KOLOM2,KOLOM3,KOLOM4,KOLOM5} ;
byte barisnya[7] = {BARIS1,BARIS2,BARIS3,BARIS4,BARIS5,BARIS6,BARIS7} ;

void setup() {
   //BARIS
   pinMode(BARIS1, OUTPUT);
   pinMode(BARIS2, OUTPUT);
   pinMode(BARIS3, OUTPUT);
   pinMode(BARIS4, OUTPUT);
   pinMode(BARIS5, OUTPUT);
   pinMode(BARIS6, OUTPUT);
   pinMode(BARIS7, OUTPUT); 

   //KOLOM
   pinMode(KOLOM1, OUTPUT);
   pinMode(KOLOM2, OUTPUT);
   pinMode(KOLOM3, OUTPUT);
   pinMode(KOLOM4, OUTPUT);
   pinMode(KOLOM5, OUTPUT);

}




Tujuan membuat array yang isinya PIN I/O untuk kolom dan baris adalah memudahkan proses geser BIT saat scanning dan penyalaan LED. Ini karena arduino menggunakan penamaan PIN sebagai Port I/O tersendiri bukan seperti Attiny dan microcontroler AVR lainnya yg PORT disesuaikan dengan register portnya masing-masing selebar 8 bit sehingga mudah melakukan operasi geser bit. Ini bedanya tukang solder yg pernah belajar microcontroller menggunakan bahasa assembly dengan yang langsung lompat menggunakan arduino. Kalau anda langsung menggunakan Arduino mungkin akan kebingungan memahaminya.


- Function Untuk Menulis Karakter




void tulis(int lama, byte *dot)
{

for(int a=0 ; a<lama ; a++)
{
 for(int b=0 ; b<5 ; b++)         
  {

   for( int c=0;c<5 ; c++){
       if( c == b) digitalWrite(kolomnya[c],LOW );
       else digitalWrite(kolomnya[c],HIGH );
        }
   

   for(int d=0;d<7;d++) {
         digitalWrite(barisnya[d], ((1<<d) & dot[b]) >> d );       
         }
   delay(2);
   blank();
   delay(1);    
  }
 }
}



Kita akan bahas baris per baris fungsi diatas agar gampang memahaminya.


void tulis(int lama, byte *dot)


Lama = waktu lama for loop dijalankan agar menunjukan lama tampilnya sebuah karakter.
*dot   = Pointer ke array yang akan melewatkan 7 bit baris karakter

Terdapat 4 buah FOR LOOP yaitu :

a = Loop lama tampil sebuah karakter 
b = Scanning KOLOM
c = Geser kolom (LOW)
d = Geser baris (HIGH)

Kita akan breakdown for loop C dan D :

for( int c=0;c<5 ; c++){
       if( c == b) digitalWrite(kolomnya[c],LOW );
       else digitalWrite(kolomnya[c],HIGH );
        }

Ketika scanning kolom satu persatu maka yg bergerak adalah memberikan pin i/o sebagai  LOW / 0, jadi kalau diberikan perintah secara manual akan menjadi  :






if ( b == 0 ) { 
                        digitalWrite(KOLOM1, LOW);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                    }

else if ( b == 1 ) { 
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, LOW);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                    }

else if ( b == 2 ) { 
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, LOW);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                    }

else if ( b == 3 ) { 
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, LOW);
                        digitalWrite(KOLOM1, HIGH);
                    }

else if ( b == 4 ) { 
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, HIGH);
                        digitalWrite(KOLOM1, LOW);
                    }






Terlalu panjang, namun mudah dimengerti dan merupakan terjemahan isi dari FOR LOOP C yang hanya 4 baris saja.


for(int d=0;d<7;d++) {
    
      digitalWrite(barisnya[d], ((1<<d) & dot[b]) >> d );       
         
     }

For Loop D memiliki keunggulan geser bit dengan hanya sebaris script, tapi untuk memahaminya butuh penjabaran yaitu :

GESER BIT  1 :  (1<<d) & dot[b] 
GESER BIT  2 :   >> d 

Semisal nih..7 BIT baris yg akan dinyalakan adalah 0b0001100 , dimana 0 = mati , 1 = nyala. Sehingga kita perlu mengetahui bit yg sesuai dengan PIN i/o yg bersesuaian juga. Inilah hubungan kita membuat ARRAY yg berisikan nomer PIN. 

Jadi dengan 7 kali loop maka kita akan tau PIN BARIS ke X  itu mati atau nyala. Penejelasannya seperti berikut :

saat d=0 , maka angka 1 geser kiri sebanyak 0 kali = 0000001 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000000, kemudian geser kanan semuanya sebanyak 0 kali hasilnya PIN BARIS1 = 0 /MATI

saat d=1 , maka angka 1 geser kiri sebanyak 1 kali = 0000010 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000000, kemudian geser kanan semuanya sebanyak 1 kali hasilnya PIN BARIS2 = 0 /MATI

saat d=2 , maka angka 1 geser kiri sebanyak 2 kali = 0000100 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000100, kemudian geser kanan semuanya sebanyak 2 kali hasilnya PIN BARIS3 = 1 /NYALA


saat d=3 , maka angka 1 geser kiri sebanyak 3 kali = 0001000 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00001000, kemudian geser kanan semuanya sebanyak 3 kali hasilnya PIN BARIS4 = 1 /NYALA

saat d=4 , maka angka 1 geser kiri sebanyak 4 kali = 0010000 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000000, kemudian geser kanan semuanya sebanyak 4 kali hasilnya PIN BARIS5 = 0 /MATI

saat d=5 , maka angka 1 geser kiri sebanyak 5 kali = 0100000 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000000, kemudian geser kanan semuanya sebanyak 5 kali hasilnya PIN BARIS6 = 0 /MATI

saat d=6 , maka angka 1 geser kiri sebanyak 6 kali = 1000000 , lanjut di AND dengan isi semuanya  0001100 hasilnya = 00000000, kemudian geser kanan semuanya sebanyak 6 kali hasilnya PIN BARIS7 = 0 /MATI


Seperti itulah proses geser BIT sehingga tiap LED dapat ditentukan mati dan nyalanya .

   delay(2);
   blank();
   delay(1);    


Fungsi blank mengatasi kelembaman mata yg menyebabkan efek LED berbayang (saking cepetnya ) dengan cara mematikan semua LED saat akan pindah  7 bit Baris selanjutnya 


 void blank ()
 {
   digitalWrite(BARIS1,LOW);
   digitalWrite(BARIS2,LOW);
   digitalWrite(BARIS3,LOW);
   digitalWrite(BARIS4,LOW);
   digitalWrite(BARIS5,LOW);
   digitalWrite(BARIS6,LOW);
   digitalWrite(BARIS7,LOW);
   
 }


- Sedangkan untuk LOOP utama cukup singkat aja 

void loop() {


 tulis(10,love1);
 tulis(10,love2);

 }


- Hasilnya :





Selanjutnya ada fasilitas text geser kanan dan naik



Tinggal mengolah sedikit script pada tulisan sebelumnya di 2011 di link disini.

Bagaimana ? SELAMAT MENCOBA !
Share:

Senin, 29 Juli 2013

Tutorial: Jam 6 Digit + Kalender Dengan Attiny 2313




Siapkan bahan-bahan  seperti berikut:

Attiny 2313 + downloader isp
Bagian power supply

  •     Trafo AC atau Adaptor yang dapat diatur tegangannya
  •     Jika menggunakan Trafo AC, maka ubah-ubah terminal sekunder trafo untuk V Segmen
  •     7805 untuk menurunkan tegangan ke 5V
  •     Baterai backup 3v - 4.5 v

Dioda 1N4002 (4 + 1 )atau Dioda Bridge sebagai penyearah jika memakai Trafo AC
Capasitor 1000uF/25v , 100nF, 22pF (2buah) atau Varco 0-50pF
Resistor 10K (3 buah), 1K 2Buah
Led 4 buah sebagai pembatas digit
ULN 2003
OptoIsolator PC817 atau 4N25 atau yang sejenis (6 buah)
Xtal 4MHz atau sesuai keinginan
Push Buton tactile (2 buah)
7 segment common Anoda ukuran terserah (6 buah)


SKEMATIK




klik untuk memperjelas

Keterangan:


  1. Gunakan power supply berbeda (yang dapat diubah-ubah) untuk V SEGMEN sehingga dapat mengatur kecerahan dari 7 segmen
  2. Untuk mengkompensasi ketidak akuratan xtal, maka salah satu load cap dari xtal dibuat variabel
  3. Nilai Xtal yang digunakan disesuaikan dengan xtal yg tersedia dipasaran, jika berbeda maka silahkan baca pembahasan mengenai counter/timer disini.
  4. Baterai backup akan mencatu attiny jika listrik mati (tanpa display) sehingga time keeping tetap jalan.


SCRIPT


#define F_CPU 4000000UL //sesuaikan xtal yg dipakai
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <string.h>

uint8_t jam,menit,detik,bulan,tanggal,tahun,clock,menu,mode,blink; 
uint8_t a = 0;
char bul_max[12]={31,28,31,30,31,30,31,31,30,31,30,31} ;





//tampilan 7 digit 7 segmen dan animasi

void segmen(uint8_t digit)

{
    switch (digit)        
          {

  case 0 :  
     {

   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3)  & ~_BV(PB4) 
            & ~_BV(PB5)  & ~_BV(PB6);

            PORTB |= _BV(PB7);
   
   break;
           }
  case 1 :
     {
      
   PORTB &= ~_BV(PB2) & ~_BV(PB3);

            PORTB |= _BV(PB1)|  _BV(PB4)|  _BV(PB5)|  _BV(PB6)|  _BV(PB7);
   
   break;
           }
  case 2 : 
     {
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB7) & ~_BV(PB5) & ~_BV(PB4);

            PORTB |= _BV(PB3)|  _BV(PB6) ;
   
      break;
           }  
  case 3 : 
      {

   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB7);

            PORTB |= _BV(PB5)|  _BV(PB6) ;
        
   break;
           }
  case 4 :
     {
      
   PORTB &= ~_BV(PB6) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB7) ;

            PORTB |= _BV(PB4)|  _BV(PB5) |  _BV(PB1);
   
   break;
           }
  case 5 : 
     {

   PORTB &= ~_BV(PB1) & ~_BV(PB3)  & ~_BV(PB4) & ~_BV(PB7)  & ~_BV(PB6);

            PORTB |= _BV(PB2) |  _BV(PB5);
   
   break;
           }
  case 6 : 
     {

   PORTB &= ~_BV(PB1) & ~_BV(PB3)  & ~_BV(PB4) & ~_BV(PB7)  & ~_BV(PB6) & ~_BV(PB5);

            PORTB |= _BV(PB2) ;
   
      break;
           }
  case 7 : 
     {

   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3);

            PORTB |=  _BV(PB4)|  _BV(PB5)|  _BV(PB6)|  _BV(PB7);
   
      break;
           }  
  case 8 : 
     {
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3)  & ~_BV(PB4) 
            & ~_BV(PB5)  & ~_BV(PB6)  & ~_BV(PB7);

      break;
           }
  case 9 : 
     {

   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3)  & ~_BV(PB4) 
             & ~_BV(PB6)  & ~_BV(PB7);

   PORTB |= _BV(PB5); 

      break;
           }
  case 10 :
     {
         PORTB |= _BV(PB1) |  _BV(PB2) |  _BV(PB3) |  _BV(PB4)|
                _BV(PB5) | _BV(PB6) |  _BV(PB7) ;

      break;
           }
  case 11 :
     {
         PORTB &= ~_BV(PB1);

      PORTB |=  _BV(PB2) |  _BV(PB3) |  _BV(PB4)|
                _BV(PB5) | _BV(PB6) |  _BV(PB7) ;
                

      break;
           }
  case 12 :
     {
         PORTB &= ~_BV(PB4);

      PORTB |=  _BV(PB2) |  _BV(PB3) |  _BV(PB1)|
                _BV(PB5) | _BV(PB6) |  _BV(PB7) ;
                

      break;
           }

  case 13 :
     {
         PORTB &= ~_BV(PB2);

      PORTB |=  _BV(PB4) |  _BV(PB3) |  _BV(PB1)|
                _BV(PB5) | _BV(PB6) |  _BV(PB7) ;
                

      break;
           }

  case 14 :
     {
         PORTB &= ~_BV(PB3);

      PORTB |=  _BV(PB2) |  _BV(PB4) |  _BV(PB1)|
                _BV(PB5) | _BV(PB6) |  _BV(PB7) ;
                

      break;
           }
  case 15 :
     {
         PORTB &= ~_BV(PB5);

      PORTB |=  _BV(PB2) |  _BV(PB3) |  _BV(PB1)|
                _BV(PB4) | _BV(PB6) |  _BV(PB7) ;
                

      break;
           }
  case 16 :
     {
         PORTB &= ~_BV(PB6);

      PORTB |=  _BV(PB2) |  _BV(PB3) |  _BV(PB1)|
                _BV(PB5) | _BV(PB4) |  _BV(PB7) ;
                

      break;
           }

      }

         PORTB =  _BV(PB0) | ~PORTB; //khusus memakai uln2003


}


//posisi scan digit

void posisi(uint8_t pos)

{
    switch (pos)   
    {
    case 0 :  
     {

            PORTD &=  ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5)  & ~_BV(PD6) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }

    case 1 :  
     {

            PORTD |= _BV(PD0);

            PORTD &= ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5)  & ~_BV(PD6) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }

    case 2 :  
     {

            PORTD |= _BV(PD1);

            PORTD &= ~_BV(PD0) & ~_BV(PD6) & ~_BV(PD4)  & ~_BV(PD5) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }

    case 3 :  
     {

            PORTD |= _BV(PD4);

            PORTD &= ~_BV(PD1) & ~_BV(PD0) & ~_BV(PD5)  & ~_BV(PD6) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }


    case 4 :  
     {

            PORTD |= _BV(PD5);

            PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4)  & ~_BV(PD6) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }

    case 5 :  
     {

            PORTD |= _BV(PD6);

            PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4)  & ~_BV(PD5) ;
   
   PORTB &= ~_BV(PB0);
               
   break;
           }


    case 6 :  
     {

            PORTB |= _BV(PB0);

            PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5)  & ~_BV(PD6) ;
   
               
   break;
           }
         }

}


void animasi(void) //animasi pindah jam-kalender

{
     posisi(1);
     segmen(11);
  _delay_ms(50);
     posisi(2);
     segmen(11);
  _delay_ms(50);
     posisi(3);
     segmen(11);
  _delay_ms(50);
     posisi(4);
     segmen(11);
  _delay_ms(50);
     posisi(5);
     segmen(11);
  _delay_ms(50);

     posisi(6);
     segmen(11);
  _delay_ms(50);
     segmen(13);
  _delay_ms(50);
     segmen(14);
  _delay_ms(50);

     posisi(5);
     segmen(12);
  _delay_ms(50);
     posisi(4);
     segmen(12);
  _delay_ms(50);
     posisi(3);
     segmen(12);
  _delay_ms(50);
     posisi(2);
     segmen(12);
  _delay_ms(50);

     posisi(1);
     segmen(15);
  _delay_ms(50);
     segmen(16);
  _delay_ms(50);

}


void tulis(void) //tulis ke 7 segmen

{

     posisi(1);
 
 if(menu == 1 && TCNT1 < 20000) segmen(10); //edit jam
 else    segmen((jam/10));
  _delay_ms(1);
     segmen(10);


     posisi(2);
 if(menu == 1 && TCNT1 < 20000) segmen(10); //edit jam
 else  segmen((jam%10));
  _delay_ms(1);
     segmen(10);

 
 
     posisi(3);
 if(menu == 2 && TCNT1 < 20000) segmen(10); //edit menit
 else    segmen((menit/10));
  _delay_ms(1);
     segmen(10);


     posisi(4);
 if(menu == 2 && TCNT1 < 20000) segmen(10); //edit menit
 else    segmen((menit%10));
     _delay_ms(1);
     segmen(10);

     
  posisi(5);
 if(menu == 3 && TCNT1 < 20000) segmen(10); //edit detik
 else     segmen((detik/10));
  _delay_ms(1);
     segmen(10);

    
  posisi(6);
 if(menu == 3 && TCNT1 < 20000) segmen(10); //edit detik
 else    segmen((detik%10));
  _delay_ms(1);
     segmen(10);


}

void tanggalan(void)

{

     posisi(1);
  if(menu == 4 && TCNT1 < 20000) segmen(10); //edit tgl
 else   segmen((tanggal/10));
  _delay_ms(1);
     segmen(10);


     posisi(2);
  if(menu == 4 && TCNT1 < 20000) segmen(10); //edit tgl
 else    segmen((tanggal%10));
  _delay_ms(1);
     segmen(10);

     posisi(3);
  if(menu == 5 && TCNT1 < 20000) segmen(10); //edit bulan
 else    segmen((bulan/10));
  _delay_ms(1);
     segmen(10);


     posisi(4);
  if(menu == 5 && TCNT1 < 20000) segmen(10); //edit bulan
 else    segmen((bulan%10));
     _delay_ms(1);
     segmen(10);

     
  posisi(5);
  if(menu == 6 && TCNT1 < 20000) segmen(10); //edit tahun
 else    segmen((tahun/10));
  _delay_ms(1);
     segmen(10);

    
  posisi(6);
 if(menu == 6 && TCNT1 < 20000) segmen(10); //edit tahun
 else     segmen((tahun%10));
  _delay_ms(1);
     segmen(10);


}


//INTERUPT 1 DETIK

ISR(TIMER1_COMPA_vect) 

{ 


detik++;
clock++;


if(detik == 60)

{  
   detik=0;
   menit++;

if(menit == 60)

     { menit=0; 
       jam++;
     }

if (jam == 24) 

{ tanggal++; jam = 0 ; }

       
    if(tahun%4 == 0) bul_max[1]=29;
       else bul_max[1]=28; 

if (tanggal > bul_max[bulan-1]) {bulan++; tanggal =1 ;}

if (bulan > 12) {tahun++;  bulan=1; }



}




}


void tombol(void)
{

if(bit_is_clear(PIND, PIND2)) 
   { 

if(menu == 0) menu =1;

else if (menu == 1) menu=2;

else if (menu == 2) menu=3; 

else if (menu == 3) menu=4; 

else if (menu == 4) menu=5; 

else if (menu == 5) menu=6; 

else if (menu == 6) menu=0; 

 
_delay_ms(200);

 }




else if(bit_is_clear(PIND, PIND3)) 
   { 

if(mode==0 && menu == 0)
{ animasi();  
  mode=1; 
  clock=0; }

else if(mode ==1 && menu ==0)
{mode=0;
clock=0;
}


if(menu == 1) 
{ jam ++;
  if (jam == 24) jam =0;
}

else if(menu == 2) 
{ menit ++;
  if (menit == 60) menit =0;
}

else if(menu == 3) detik = 0;

else if(menu == 4) 
{ tanggal++;
  if (tanggal == 32) tanggal =1;
}

else if(menu == 5) 
{ bulan++;
  if (bulan == 13) bulan =1;
}

else if(menu == 6) 
{ tahun++;
  if (tahun == 100) tahun=0;
}


_delay_ms(200);

}


}

int main(void)
{



 
 DDRD |= _BV(PD0) | _BV(PD1) | _BV(PD4) | _BV(PD5) | _BV(PD6) ; //scan digit
 DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) | _BV(PB7) ; //segment
 DDRD &= ~_BV(PD2) & ~_BV(PD3); //tombol
  

// ------------ini untuk xtal 4Mhz----------------------
   TCCR1B |= (1 << WGM12); 
   TIMSK |= (1 << OCIE1A); 
   OCR1A  = 62499;
   TCCR1B |= (1 << CS11)|(1 << CS10); 
//------------------------------------------------------

 

jam = 0;
menit= 0;
detik=0;
tanggal=1;
bulan=1;
tahun=11;
clock=0; //perpindahan animasi jam dan kalender
mode=0;
menu=0;

sei();



 while(1)
 {
     
     if(clock == 40 && mode == 1 && menu == 0)
    { animasi();}

  else if(clock > 40 && clock <50 && mode == 1 && menu == 0) 
       {
        
        tanggalan();
    }
     else if(clock == 50 && mode == 1 && menu == 0)

   { animasi(); clock =0; }
  
  else if(menu == 0)
  { tulis(); }

  else if(menu > 3)
  { tanggalan(); }

  else 
  { tulis(); }

         
tombol();   

    }
return 0;
}




ALTERNATIF UNTUK 7 SEGMEN LEBIH BESAR

Optoisolator PC817 mempunyai kekurangan yaitu dayanya kecil sehingga arus yg dapat dialirkan kecil saja. Hal ini akan menyebabkan 7 segmen besar menjadi redup sehingga perlu ditambahkan transistor yg memiliki daya lebih dan dengan rangkaian common Emiter menggunakan transistor PNP seperti BD140  dan PC817 sebagai control base nya (bisa juga transistor NPN 2N3906/2222)  dengan contoh rangkaian pengganti sebagai berikut:





HASIL




SELAMAT MENCOBA
Share:

Kamis, 17 Januari 2013

BERMAIN DENGAN TV PART #3 - OSD (Composite Video Text Overlay) dengan Attiny2313




Text Overlay atau On Screen Display (OSD) merupakan fitur yang umum dijumpai pada televisi modern. Gambar composite (AV in) dapat ditumpuk dengan text seperti text berjalan (scroll text / crawler) , logo , jam dan berbagai macam sesuai keinginan. Bagaimana cara menimpa gambar video dengan text akan kita bahas disini, dan diharapkan membaca penjelasan mengenai dasar-dasar bermain televisi menggunakan microcontroller disini:  PART#1  PART#2  JAM TV



Courtesy of  VIENA WIRELESS SOCIETY 


Gunakan rangkaian yg terhubung dengan AIN saja, yg di dekat TX RX diabaikan saja


Pada web aslinya yang digunakan ic microcontroller  ATMega8 ,prinsip utamanya memanfaatkan analog komparator untuk mendeteksi sinkronisasi vertikal & horisontal dari sinyal input video composit (semisal dari kamera atau dvd).


Pada script di web asli dijelaskan bahwa yg digunakan video NTSC..karena di indonesia menggunakan PAL maka saya ubah script menjadi PAL dan menggunakan ATTINY



dari gambar ic attiny 2313 kita akan menggunakan pin AIN0 dan AIN1 serta pin MOSI, dan beberapa pin digunakan sebagai tombol seperlunya, rangkai sesuai gambar asli. gunakan nilai komponen sesuai catatan dan dengan bereksperimen maka akan didapat efek2 yg tidak diduga seperti warna text, warna latar dsb.


untuk itu kita bahas script satu persatu ...


>>> Header <<



#define F_CPU 20000000UL //xtal 20MHz

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/pgmspace.h>

#include <avr/sleep.h>





#define FONTHEIGHT 12 //panjang text



//rumus dan variabel syncronisasi

#define HSYNC PORTB=0;

#define GREY PORTB=0x80;

#define COL(r) textnya=word[r][fontline];



static uint8_t fontline = 0;

static uint8_t fontzoom = 0;

static uint16_t rasterline=0;



// ARRAY untuk tulisan nomer 0,1,2 dst



const unsigned char font[12][FONTHEIGHT] PROGMEM = { 

   {

 0b00000000,

 0b01111100,

 0b11000110,

 0b11001110,

 0b11011110,

 0b11010110,

 0b11110110,

 0b11100110,

 0b11000110,

 0b01111100,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b00010000,

 0b00110000,

 0b11110000,

 0b00110000,

 0b00110000,

 0b00110000,

 0b00110000,

 0b00110000,

 0b11111100,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b01111000,

 0b11001100,

 0b11001100,

 0b00001100,

 0b00011000,

 0b00110000,

 0b01100000,

 0b11001100,

 0b11111100,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b01111000,

 0b11001100,

 0b00001100,

 0b00001100,

 0b00111000,

 0b00001100,

 0b00001100,

 0b11001100,

 0b01111000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b00001100,

 0b00011100,

 0b00111100,

 0b01101100,

 0b11001100,

 0b11111110,

 0b00001100,

 0b00001100,

 0b00011110,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b11111100,

 0b11000000,

 0b11000000,

 0b11000000,

 0b11111000,

 0b00001100,

 0b00001100,

 0b11001100,

 0b01111000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b00111000,

 0b01100000,

 0b11000000,

 0b11000000,

 0b11111000,

 0b11001100,

 0b11001100,

 0b11001100,

 0b01111000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b11111110,

 0b11000110,

 0b11000110,

 0b00000110,

 0b00001100,

 0b00011000,

 0b00110000,

 0b00110000,

 0b00110000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b01111000,

 0b11001100,

 0b11001100,

 0b11101100,

 0b01111000,

 0b11011100,

 0b11001100,

 0b11001100,

 0b01111000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b01111000,

 0b11001100,

 0b11001100,

 0b11001100,

 0b01111100,

 0b00011000,

 0b00011000,

 0b00110000,

 0b01110000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b00000000,

 0b00000000,

 0b00110000,

 0b00110000,

 0b00000000,

 0b00000000,

 0b00110000,

 0b00110000,

 0b00000000,

 0b00000000,

 0b00000000,

 },

 {

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 }};





//variabel pelengkap



uint8_t word[7][12];

int y;

uint8_t jam,menit,detik,textnya,tick;







>>> timer untuk horisontal sync PAL (64us) <<


void timer_init(void){



 TCCR1B |= (1<<WGM12);

 TIMSK |= (1<<OCIE1A);

 OCR1A = 1280; //64*16;

 TCCR1B |= (1<<CS10);



}





>> geser2 bit untuk menampilkan angka dari Array <<



void geser(void)

{ 

PORTB = (textnya  & 0x80) +0x8  ;

textnya <<=1;

PORTB = (textnya  & 0x80) +0x8 ;

textnya <<=1;

PORTB = (textnya  & 0x80)  +0x8 ;

textnya <<=1;

PORTB = (textnya  & 0x80)  +0x8 ;

textnya <<=1;

PORTB = (textnya  & 0x80)  +0x8 ;

textnya <<=1;

PORTB = (textnya  & 0x80)   +0x8;

textnya <<=1;

PORTB = (textnya  & 0x80)   +0x8 ;

textnya <<=1;

PORTB = (textnya  & 0x80)   +0x8 ;



}





>> proses tulis tiap 1us dari frame horisontal 64us <<




void tulis(void){



//31 & 43 adalah batas tinggi karakter 12 scan/rasterline/vsync

//y adalah posisi rasterline(Vsync) yg sedang ditulis

 if( rasterline > (31+y) && rasterline <= (43+y) ) {

  _delay_us(8);

    COL(0);

    geser();

    COL(1);

    geser();

    COL(2);

    geser();

    COL(3);

    geser();

    COL(4);

    geser();

    COL(2);

    geser();

    COL(5);

    geser();

    COL(6);

    geser();

       PORTB=0;

      _delay_us(1);

  fontline++; //pindah ke array selanjutnya

 } 

//jika tidak menulis 

   else { 

  _delay_us(8);

   fontline = 0;

  fontzoom=0;

   }



// yang ini batas scannline trus bisa sisipkan proses

//      memasukkan data ke memory 

//  sesuaikan karena kaskus merubah text &word; (hilangkan ' ; ') 

 if( rasterline > 311 )

  { memcpy_P(&word;[0],&font;[jam/10],12);

   memcpy_P(&word;[1],&font;[jam],12);

   memcpy_P(&word;[2],&font;[10],12);

   memcpy_P(&word;[3],&font;[menit/10],12);

   memcpy_P(&word;[4],&font;[menit],12);

   memcpy_P(&word;[5],&font;[detik/10],12);

   memcpy_P(&word;[6],&font;[detik],12);

 

      }

}



// interupt 64us 

ISR (TIMER1_COMPA_vect) {



rasterline = 0;



}



>> comparator untuk mendeteksi awal Vsync dan Hsync <<



SIGNAL(SIG_COMPARATOR)



{ //trik mendeteksi hsync dan vsync dengan melihat lama blanking



 TCNT1=0; // reset timer

 while(TCNT1<70); // wait 5us to see if H or V sync



 if(!((ACSR>>ACO)&1)) { // its an H sync

  TCNT1=0; // reset timer

  rasterline++;

  tulis();

 }

 else { // this a V sync

  rasterline=0;

    

//sekalian aja ditambah timer untuk nambah detik

  tick++;

    if(tick >= 200){

    tick=0;

       detik++;

    if(detik==60){

      menit++;

   detik=0;}



       if(menit==60){

    menit=0;

    jam++;}

    if (jam==24) jam=0;

  }

 }

}  





>> Tombol untuk ubah jam dan geser2 posisi jam <<




void tombol(void)

{

if(bit_is_clear(PIND, PIND3)) 

{

jam++;



if(jam == 24) jam=0;



detik=0;

_delay_ms(200);

}



else if(bit_is_clear(PIND, PIND4))

{

menit++;  



if(menit == 60) menit =0;





detik=0;

_delay_ms(200);

}



else if(bit_is_clear(PIND, PIND5)) //naik

{

y-=3;



if(y<1) y=1;



_delay_ms(200);

}



else if(bit_is_clear(PIND, PIND6)) //turun

{

y+=3;



if(y>300) y=300;



_delay_ms(200);

}






>> main program<<




int main() {

tick=0;

jam=22;

menit=19;

detik=44;

rasterline=0;

y=0; //variable posisi text

    



    ACSR = (1<<ACIE)|(1<<ACIS0)|(1<<ACIS1);  //analog comparator

    DDRD &=~(1<<PD3) & ~(1<<PD4)&~(1<<PD5) & ~(1<<PD6) ; //tombol

    

  // data text dan MISO, PB0 pada web asli dirubah jadi PB3 attiny 

    DDRB |= (1<<PB7)|(1<<PB3);

  



        timer_init(); //idupin timer

    

 set_sleep_mode(SLEEP_MODE_IDLE); //menghemat tenaga



 sei();



 for( ;; )tombol();

}





rangkaian ini cocok buat nambahin text ke kamera CCTV murah yg ga ada textnya, jadi bisa ditambahin jam atau text penanda nomer kamera




SELAMAT MENCOBA
Share:

Rabu, 19 Desember 2012

PALANG PINTU KERETA API OTOMATIS DENGAN ATTINY2313


Palang pintu kereta api yg kita bahas kali ini pernah saya buat kira-kira setahun yang lalu dalam rangka membantu teman yang kesusahan mengerjakan tugas. Dia mewanti-wanti saya agar tidak menyebarkannya di blog sampai saatnya dia lulus kuliah. Dan saatnya kini kita bahas karena teman saya itu sudah lulus akhirnya.


Bahan utama yang kita perlukan adalah motor stepper. Dipasaran komponen elektronika, motor stepper dijual umumnya memiliki kumparan berjenis BIPOLAR, dimana nantinya diperlukan sebuah driver H-bridge untuk merubah polaritas kumparannya. Sedangkan jika beruntung (cari di loakan) atau punya duit berlebih, maka motor stepper UNIPOLAR tentunya menjadi pilihan yang lebih simple.

Cara mudah membedakan jenis motor steep adalah jumlah kabel, untuk bipolar biasanya memiliki kabel 4 , sedangkan unipolar memiliki kabel 5 dimana 1 kabel sebagai common (supply)



File:Drive.png
cara menggerakkan motor stepper (courtesy wikipedia)



Prinsip sensor yang digunakan untuk mendeteksi kereta datang dan pergi maka diletakkan sensor "cahaya terhalang" menggunakan pasangan LED INFRARED & PHOTODIODA yang biasanya digunakan sebagai transmiter & receiver untuk remote TV. Kedua led ini diposisikan berhadap-hadapan (sebaiknya diberi casing/ penghalang cahaya dari samping) sehingga ketika tanpa halangan, dengan rangkaian tambahan resistor pull down dan anoda ke 5v , photodioda akan memberikan logika 1 (seperti tehubung langsung ke 5v). Kondisi ketika sinar infre merah terhalang maka photo dioda akan memutus hubungan dari 5V dan rangkaian menjadi logika 0 karena terhubung melalui resistor 10k ohm menuju ground (0v).

Untuk mendeteksi kedatangan kereta api, maka sensor "kedatangan" akan mendeteksi perubahan dari 1 ke 0 (falling edge) sehingga dalam script ditunjukkan dengan INTERUPT 0 yang diinisialisasikan sebagai falling edge. Sedangkan sensor untuk "kereta sudah lewat" menggunakan logika interupt rising edge (0 ke 1), dimana ketika kereta masih berada di perlintasan akan menghalangi sinar led infra (kondisi logika 0). Setelah semua rangkaian lewat maka sinar akan kembali mengaktifkan logika 1 pada photodioda.



MCUCR |= (1<<ISC01) | (0<<ISC00) |(1<<ISC11) | (1<<ISC10); 



Sensor yang ketiga merupakan sensor posisi awal dari palang pintu, diletakkan pada posisi palang pintu terbuka penuh (90 derajat) , sehingga ketika alat dihidupkan atau direset maka motor stepper akan bergerak ke kiri sampai posisi palang pintu menghalangi sinar led menuju photodioda ke 3.






Kereta api kan bolong-bolong, ada jeda antar gerbong ...nah looo...error dah....pintunya kebuka baru 1 gerbong lewat?? Tenang saja, ini hanya simulasi..kita anggap bahwa kereta api itu benda yang full kontinyu tanpa lubang jeda antar gerbong. Jika ingin menerapkan ke dunia nyata dimana ada jarak antar gerbong, maka diperlukan suatu timer yang akan mendeteksi waktu berapa milli second sinar infra yang dilewatkan lubang tersebut. Jika gerbong terakhir yang lewat tentunya waktunya lebih lama ketimbang sinar melalui celah - celah rangkaian kereta api, nah inilah pembedanya.


Trus pertanyaan lainnya, bagaimana jika yang diinginkan adalah palang pintu keretanya 2 arah ? Sekali lagi kita sebaiknya menggunakan metode timer saja, jadi kita perkirakan jika cahaya tidak terhalang selama selang waktu (misal 5 detik)  maka pintu akan terbuka.


Skematik dari palang pintu otomatis seperti berikut : 



 (klik untuk memperbesar)



Harap diperhatikan jenis motor yang digunakan dan sesuaikan driver motor yang tepat.



FULL SCRIPT METODE INTERUPT  1 ARAH:
/*

Pintu Kereta Api Otomatis
Dengan motor stepper
by: ahocool@gmail.com
SURABAYA - 2012
1 arah saja
*/


#define F_CPU 100000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


#define SPEED _delay_ms(10)  // ubah nilai delay sesuai kecepatan yang diinginkan

//stepper FULL STEP, bisa dirubah sesuai keinginan
void puter_kanan(void)

{ 
   PORTB |=_BV(PB0);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB1);
   PORTB &= ~_BV(PB0) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB2);
   PORTB &= ~_BV(PB1) & ~_BV(PB0) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB3);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB0);
   SPEED;

   PORTB |=_BV(PB0) | _BV(PB2);
   PORTB &= ~_BV(PB1)  & ~_BV(PB3) ;
}

void puter_kiri(void)

{ 
   PORTB |=_BV(PB3);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB0) ;
   SPEED;


   PORTB |=_BV(PB2);
   PORTB &= ~_BV(PB0) & ~_BV(PB1) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB1);
   PORTB &= ~_BV(PB2) & ~_BV(PB0) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB0);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;

   PORTB |=_BV(PB0) | _BV(PB2);
   PORTB &= ~_BV(PB1)  & ~_BV(PB3) ;

}

SIGNAL (SIG_INT0)
{
  int a;

   //ubah nilai max looping berikut sampai posisi berhenti yg pas
   for(a=0;a<3;a++) puter_kanan();

}

SIGNAL (SIG_INT1)
{
int a;

   //ubah nilai max looping berikut sampai posisi berhenti yg pas
   for(a=0;a<3;a++) puter_kiri();

}




int main(void)
{


   PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) ; //OUTPUT Stepper pin A,B,C,D
   PORTD &= ~_BV(PD4); //sensor posisi awal
    
   //aktifkan interupt

   MCUCR |= (1<<ISC01) | (0<<ISC00) |(1<<ISC11) | (1<<ISC10); 
   // interupt 0 (datang) falling edge, interupt 1 (pergi) rising edge

   GIMSK |= (1<<INT0) |(1<<INT1); 

   sei();

   //inisialisasi awal saat dihidupkan , pintu membuka sampai sensor posisi OFF


     
     while (bit_is_set(PIND, PIND4) )
  {
      puter_kiri(); //steper naik sampe sensor awal terhalang
      
  }

 while(1)
  {

  }

return 0;
}




FULL SCRIPT METODE TIMER - 2 ARAH :
/*
Pintu Kereta Api Otomatis
Dengan motor stepper
by: ahocool@gmail.com
SURABAYA - 2012
versi timer -- 2 arah
*/

#define F_CPU 100000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define SPEED _delay_ms(10)  // ubah nilai delay sesuai kecepatan yang diinginkan
#define TIMER 5 // timer dari gerbong terakhir menlewati sensor dan membuka palang pintu

int detik, posisi, depan;

void init_timer(void)
{
   TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
   TIMSK |= (1 << OCIE1A); // Enable CTC interrupt 
   OCR1A  = 7812; //compare the CTC A 
   TCCR1B |= (1 << CS11)|(1 << CS10); // Start timer at Fcpu/64
   TCNT1 = 0;
   detik=0;
   sei();
}

void init_sensor_fall(void)
{
    
   cli();

   //aktifkan interupt
   MCUCR |= (1<<ISC01) | (0<<ISC00) |(1<<ISC11) | (0<<ISC10); 
   // interupt 0 & 1   falling edge , untuk deteksi 2 arah

   GIMSK |= (1<<INT0) |(1<<INT1); 

   sei();

   posisi = 0 ; // sebagai penanda kalo posisi pintu terbuka
}


void init_sensor_rise(void)
{
   cli();
   //aktifkan interupt
   MCUCR |= (1<<ISC01) | (1<<ISC00) |(1<<ISC11) | (1<<ISC10); 
   // interupt 0 & 1   rising edge , untuk deteksi akhir gerbong

   GIMSK |= (1<<INT0) |(1<<INT1); 

   sei();

   posisi = 1 ; // sebagai penanda kalo posisi pintu tertutup
}


void puter_kanan(void)

{ 
   PORTB |=_BV(PB0);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB1);
   PORTB &= ~_BV(PB0) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB2);
   PORTB &= ~_BV(PB1) & ~_BV(PB0) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB3);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB0);
   SPEED;

   PORTB |=_BV(PB0) | _BV(PB2);
   PORTB &= ~_BV(PB1)  & ~_BV(PB3) ;
}

void puter_kiri(void)

{ 
   PORTB |=_BV(PB3);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB0) ;
   SPEED;


   PORTB |=_BV(PB2);
   PORTB &= ~_BV(PB0) & ~_BV(PB1) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB1);
   PORTB &= ~_BV(PB2) & ~_BV(PB0) & ~_BV(PB3) ;
   SPEED;


   PORTB |=_BV(PB0);
   PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) ;
   SPEED;

   PORTB |=_BV(PB0) | _BV(PB2);
   PORTB &= ~_BV(PB1)  & ~_BV(PB3) ;

}

SIGNAL (SIG_INT0)
{
  int a;
  
  
   //jika pintu terbuka dan kereta lewat  
   if( posisi == 0) {
       depan = 1; //berarti sensor 1 jadi yg didepan
       init_sensor_rise(); //mode interupt berubah
  
   //ubah nilai max looping berikut sampai posisi berhenti yg pas
       for(a=0;a<3;a++) puter_kanan();
     
                 }
   else {
   //jika ada kondisi celah gerbong (0 -> 1) maka reset timer
     if(depan == 1)init_timer(); 
   
        }
}

SIGNAL (SIG_INT1)
{
int a;
   
    //jika pintu terbuka dan kereta lewat 
     if( posisi == 0) {
       depan = 2; //berarti sensor 2 jadi yg didepan
       init_sensor_rise();//mode interupt berubah 
  
   //ubah nilai max looping berikut sampai posisi berhenti yg pas
       for(a=0;a<3;a++) puter_kanan();
     
                 }
   else {
   //jika ada kondisi celah gerbong (0 -> 1) maka reset timer
     if(depan == 2)init_timer(); 
   
        }
}



ISR(TIMER1_COMPA_vect) // interupt timer detik

{ 
int a;


detik++;

if(detik >= TIMER ) // jika lebih dari timer yg ditentukan maka pintu terbuka

  {

    init_sensor_fall(); //kembalikan sensor sebagai interupt fall edge
    TIMSK=0; //matikan timer


   //ubah nilai max looping berikut sampai posisi berhenti yg pas
   for(a=0;a<3;a++) puter_kiri();
   
  }
}



int main(void)
{


   PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) ; //OUTPUT Stepper pin A,B,C,D
   
   PORTD &= ~_BV(PD2) & ~_BV(PD3) & ~_BV(PD4); //sensor sebagai input
    
   init_sensor_fall(); //awal sebagai interupt fall

   //inisialisasi awal saat dihidupkan , pintu membuka sampai sensor posisi OFF

  
     while (bit_is_set(PIND, PIND4) )
  {
      puter_kiri(); //steper naik sampe sensor awal terhalang
      
  }



 while(1)
 {

 }
 
   
return 0;
}





SELAMAT MENCOBA !

Share:

Rabu, 12 Desember 2012

BELAJAR ACCESS SD CARD CARA SIMPLE DENGAN ATTINY2313 - Part3


ATTINY2313 TALKING MACHINE 





Disclaimer : collected from various source on Google, writer read and modify for educational purpose only. Free to use !


Sebaiknya anda baca Part2 agar tidak kebingungan




sebelum lanjut, kita ingat project wav player dengan memory I2C  (silahkan baca disini), kapasitasnya kecil banget dan sagat pendek, kenapa tidak kita pakai SD card saja ?

ternyata kita tidak perlu pusing2, karena jika memainkan attiny pada clock 8mhz, maka waktu access SD card dan PWM sangatlah pas sehingga cukup memainkan beberapa nilai delay saja sudah mendapatkan suara yang cukup bagus (file wav PCM 6000hz 8bit)

kita ingat dulu code untuk membuat audio via PWM - OC1A, kita hilangkan sekarang beberapa pembagian dan script jadi lebih simple

Code:
void pwm_init(void)

{

    /* use OC1A pin as output */

    DDRB = _BV(PB3);



    /*

    * clear OC1A on compare match

    * set OC1A at BOTTOM, non-inverting mode

    * Fast PWM, 8bit

    */

    TCCR1A = _BV(COM1A1) | _BV(WGM10);

   

    /*

    * Fast PWM, 8bit

    * Prescaler: clk/1 = 8MHz

    * PWM frequency = 8MHz / (255 + 1) = 31.25kHz

    */

    TCCR1B = _BV(WGM12) | _BV(CS10);

   

    /* set initial duty cycle to zero */

    OCR1A = 0;

}






dan kita mainkan delay pada code pembacaan SD CARD melalui USI, untuk clock 8mhz dan file format 6000hz 8bit mengggunakan delay seperti berikut

Code:


unsigned char SPI_write(unsigned char ch){

 USIDR = ch;

    USISR |= (1<<USIOIF);

 

 do {

 USICR |= (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) | (1<<USITC);



   _delay_us(9);

   

    } while((USISR & (1<<USIOIF)) == 0);



 return USIDR;

}




THAT"S IT ....hanya itu yang dirubah, selanjutnya simpan file wav pada SD card dan dengan bantuan software winhex, kita dapat membaca sector dimana file dimulai. Jika format SD card adalah FAT16, maka jika file dicopy setelah di format ulang akan diletakkan di posisi sector 555. Karena memory attiny yang kecil, maka ga usah dibingungkan dengan pembacaan root, FAT1, FAT2 dan sebagainya. Kita baca dulu saja via winhex kemudian dimanfaatkan. Seperti pada skematik berikut, saya akan memutar audio setelah tombol dipencet...file audio saya rekam dari laptop.



(klik biar tambah gede)

audio output pada OC1A bisa menggunakan amplifier sederhana seperti diatas, atau bisa juga membuat yg lebih paten, semisal menggunakan opamp LM386 atau TDA2003 (googling aja)


Langkah selanjtunya adalah memformat SDcard dan membuat file audio yang akan diputar (bisa dipotong dari mp3 atau direkam dan jangan lupa diconvert ke WAV PCM 6000Hz 8 bit). Sebagai contoh saya mempunyai 4 file dan copykan ke SD card. Selanjutnya buka SD menggunakan winhex seperti gambar berikut :



dan tampilan snapshot SD card dan file-filenya seperti berikut:



untuk mengetahui awal dan akhir sector dari file maka kita baca FAT1 atau FAT2 yang berisikan informasi dari isi file. Tiap file yg ada pada SD card memiliki "alokasi" pada FAT ini dimana 2byte berarti 1 cluster dari file. Untung saja winhex memberitahu pada layar sebelah kiri kalau sedang klik pada alokasi file apa dan nomer sector berapa. seperti pada gambar diatas , kita hanya perlu mencari awal cluster dan akhir cluster (ditandai dengan FF FF). Kemudian kita catat seperti yang saya dapatkan.

Code:
tombol3.wav =  cluster  2 - 18    

silahkan.wav = cluster 19 - 43   

tombol1.wav = cluster  44 - 62    

tombol2.wav =  cluster 63 - 82      



ingat cluster = sector





sedangkan untuk physical sector, cukup dengan menambahkan 553 (bukan 555 karena sector 0-1 dianggap tidak ada oleh FAT16)



selanjutnya scriptnya kita tweak biar tambah maknyus seperti berikut , karena ada beberapa bagian dari file yang digenerate oleh wavepad editor kudu di skip biar halus.

Code:




void SD_play(unsigned long  sector_start, unsigned long  sector_end) {



char i;

int byte=0;

    SD_begin(sector_start); 

  

  for(i=0; i<100; i++) {

       SPI_write(0xFF);



    byte++;

    } //biar tidak njebluk pas pencet

    

 while(1) {





      OCR1A=SPI_write(0xFF);



    byte++; 



    if(byte>= 512 && byte<515)OCR1A=0x80; //silent 



    if(byte >= 515) { 

      OCR1A=0x80;//silent

         

      CS_DISABLE();



   byte =0;

         sector_start++;

         

        if(sector_start > (sector_end -7))break; //biar halus

  else SD_begin(sector_start);

        }  

      } 

}






selanjutnya semua script bisa didownload dimari


hasilnya kayak gini gan ....



SELAMAT MENCOBA !!
Share:

Kontak Penulis



12179018.png (60×60)
+628155737755

HP: 081331339072
Mail : ahocool@gmail.com

Site View

Categories

555 (6) 7 segmen (3) adc (4) amplifier (2) analog (10) android (11) antares (3) arduino (14) attiny (1) attiny2313 (17) blog (1) bluetooth (1) cmos (2) crypto (2) dasar (35) display (3) esp8266 (3) gcc (1) iklan (1) infrared (2) Input Output (3) iot (16) jam (6) jualan (12) kereta api (1) keyboard (1) keypad (3) kios pulsa (2) kit (6) komponen (12) komputer (3) komunikasi (1) kontrol (4) lain-lain (8) lcd (2) led (9) led matrix (6) line tracer (1) lm35 (1) memory (1) metal detector (4) microcontroller (55) mikrokontroller (7) mikrotik (5) ninmedia (2) ntp (1) paket belajar (19) palang pintu otomatis (1) parabola (38) pcb (2) praktek (2) project (33) proyek (1) python (1) radio (3) raspberry pi (4) remote (1) revisi (1) rfid (1) robot (1) rpm (2) rs232 (1) script break down (3) sdcard (3) sensor (1) sharing (3) signage (1) sinyal (1) sms (6) software (18) tachometer (2) telepon (7) televisi (72) television (5) transistor (1) troubleshoot (3) tulisan (59) tutorial (78) tvri (2) vu meter (2) vumeter (2) wav player (3) wayang (1) wifi (3)

Arsip Blog

Diskusi


kaskus
Forum Hobby Elektronika