"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 script break down. Tampilkan semua postingan
Tampilkan postingan dengan label script break down. Tampilkan semua postingan

Rabu, 19 November 2014

[TUTORIAL & SCRIPT BREAKDOWN] RPM - TACHOMETER HONDA dengan ATTINY2313




Akhirnya balik lagi ke blog ini setelah beberapa waktu vakum. Dan kali ini menjawab beberapa request yang masuk untuk membahas lebih lanjut mengenai RPM - TACHOMETER untuk sepeda motor yang pernah dibahas disini . Sebenernya jika selalu mengikuti perkembangan blog ini maka tidak terlalu susah asal dasar pengetahuan timer dan interupt nya lengkap. 

Intinya pada project ini adalah mendeteksi RADIASI pulsa CDI ke BUSI dan dimasukkan ke PIN INTERRUPT dan kemudian dihitung jumlah pulsa yang muncul vs waktu. Dan didapatkanlah RPM yang diinginkan. Kali ini kita juga akan membuat animasi graph / level sehingga tidak bosan dengan angka-angka saja.

Perhatikan skematik dibawah ini dan bahan2nya bisa dilihat dari gambar berikut (klik untuk gambar lebih jelas)



Jangan lupa juga untuk menyediakan motor yang akan di "HIAS" yang kali ini meminjam motor anak buah saya yaitu HONDA SUPRA VIT. Saya memiliki pengalaman jika bebek honda lebih bocor sinyal CDI nya ketimbang motor lain. Jadi jika menggunakan motor lain maka disesuaikan pemilihan resistor sebelum transistor pembaca pulsa (2N3904) dan pengalaman lainnya ketika menggunakan sepeda motor Yamaha Vega maka transistor yg digunakan adalah PNP 2N3906 dengan tanpa menggunakan resistor pada basis dan VCC ke EMITOR sedangkan INTERUPT ke COLECTOR (dibalik).





Langsung aja kita bahas script nya biar ga bingung, agak panjang tapi ga rugi kok



>>>HEADER<<

Attiny 2313 yang digunakan adalah default yg memiliki clock 1MHz. 

#define F_CPU 1000000UL // sesuaikan clock yang digunakan !!
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <avr/interrupt.h>

// ini untuk animasi kata awal, ubah sesuai keinginan atau hapus jika tidak mau
uint8_t angka1=16 ;
uint8_t angka2=17 ;
uint8_t angka3=20 ;
uint8_t angka4=15 ;


uint8_t segstep=0; // untuk pindah segmen

uint8_t kalibrasi=3; // kalibrasi awal

uint8_t valid=0; // variabel untuk mengatasi noise ke tombol

int number=0; // variabel menyimpan jumlah counter



>>>PENERJEMAH ANGKA ke SEGMEN<<

7 segmen yang digunakan merupakan common Anoda sehingga untuk menyalakan segmen dibutuhkan logic "LOW" atau 0 volt / Ground. Untuk animasi dan huruf dapat dikreasikan sendiri dengan kombinasi "LOW" untuk segmen menyala dan "HIGH" untuk segmen mati.

void conv_segmen(uint8_t digit)
// Rutin ini merubah angka dan animasi ke segmen
{
    switch (digit)        
          {
//angka biasa
  case 0 :  
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB5); //PORT YG NYALA
         PORTB |= _BV(PB6) ; //PORT YG MATI 
      break;
           }
  case 1 :
     {
         PORTB &= ~_BV(PB1) & ~_BV(PB2) ;
               PORTB |= _BV(PB0) |  _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) ;
      break;
           }
  case 2 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) &  ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB6) ;
               PORTB |= _BV(PB2) |  _BV(PB5)  ;
      break;
           }  
  case 3 : 
      {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) &  ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB6) ;
               PORTB |= _BV(PB4) |  _BV(PB5)  ;
      break;
           }
  case 4 :
     {
         PORTB &= ~_BV(PB1) & ~_BV(PB2) &  ~_BV(PB5) & ~_BV(PB6)  ;
               PORTB |= _BV(PB0) |  _BV(PB3) |  _BV(PB4) ;
      break;
           }
  case 5 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB2) &  ~_BV(PB3) & ~_BV(PB5)  & ~_BV(PB6)  ;
               PORTB |= _BV(PB1) |  _BV(PB4)  ;
      break;
           }
  case 6 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB2) &  ~_BV(PB3) & ~_BV(PB4)  & ~_BV(PB5) & ~_BV(PB6) ;
               PORTB |= _BV(PB1) ;
      break;
           }
  case 7 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) &  ~_BV(PB2)  ;
               PORTB |= _BV(PB3) |  _BV(PB4) |  _BV(PB5)|  _BV(PB6) ;
      break;
           }  
  case 8 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB5) & ~_BV(PB6);
      break;
           }
  case 9 : 
     {
         PORTB &= ~_BV(PB0) & ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB5) & ~_BV(PB6);
               PORTB |= _BV(PB4) ;
      break;
           }
  case 10 : //kosong
     {
    PORTB |= _BV(PB0) | _BV(PB1) |  _BV(PB2) |  _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) ;
      break;
           }
 //11 - 14 khusus untuk animasi level       
  case 11 : 
     {
         PORTB &= ~_BV(PB4); 
               PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB5) | _BV(PB6);
      break;
           } 
   
   case 12 : 
     {
         PORTB &= ~_BV(PB4) & ~_BV(PB2); 
               PORTB |= _BV(PB0) | _BV(PB1)  | _BV(PB3) | _BV(PB5) | _BV(PB6);
      break;
           }
  case 13 : 
     {
         PORTB &= ~_BV(PB4) & ~_BV(PB2) & ~_BV(PB5); 
               PORTB |= _BV(PB0) | _BV(PB1)  | _BV(PB3) | _BV(PB6) ;
         break;
           } 
   
   case 14 : 
     {
         PORTB &= ~_BV(PB4) & ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB5); 
               PORTB |= _BV(PB0) | _BV(PB3) | _BV(PB6) ;
         break;
           }
// kebetulan nama pemilik motor seperti ini, ubah sesuai keinginan
   case 15 : //r
     {
         PORTB &= ~_BV(PB6)  & ~_BV(PB4) ; 
                       PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB3) | _BV(PB2) | _BV(PB5) ;
         break;
           }  

   case 16 : //i
     {
         PORTB &= ~_BV(PB4); 
               PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB3) | _BV(PB2) | _BV(PB5) | _BV(PB6)  ;
         break;
           }   
   
   case 17 : //b
     {
         PORTB &= ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB5) & ~_BV(PB2) & ~_BV(PB6); 
               PORTB |= _BV(PB0) |_BV(PB1)  ;
         break;
           }   

   case 18 : //y
     {

         PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB5) & ~_BV(PB6);
               PORTB |= _BV(PB4)| _BV(PB0);
      break;
           } 

   case 19 : //u
     {

         PORTB &= ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4) ;
               PORTB |= _BV(PB1)| _BV(PB0) | _BV(PB5) | _BV(PB6);
      break;
           } 

   case 20 : //0
     {
         PORTB &= ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB2) & ~_BV(PB6); 
               PORTB |= _BV(PB0) |_BV(PB1) |_BV(PB5)  ;  
      break; 
     }


}

}




>>>ANIMASI LEVEL RPM<<

Nilai RPM akan diterjemahkan dari angka menjadi level / bar graph

void animasi(uint8_t posisi)

{

switch(posisi)  {  
       case 0 :{ angka4=10; angka3=10 ; angka2=10; angka1=10;
              break; }
       case 1 :{ angka4=11; angka3=10 ; angka2=10; angka1=10;
              break; }
       case 2 :{ angka4=12; angka3=10 ; angka2=10; angka1=10;
              break; }
       case 3 :{ angka4=12; angka3=11 ; angka2=10; angka1=10;
              break; }
       case 4 :{ angka4=12; angka3=12 ; angka2=10; angka1=10;
              break; }
       case 5 :{ angka4=12; angka3=12 ; angka2=11; angka1=10;
              break; }
       case 6 :{ angka4=12; angka3=12 ; angka2=12; angka1=10;
              break; }
       case 7 :{ angka4=12; angka3=12 ; angka2=12; angka1=11;
              break; }
       case 8 :{ angka4=12; angka3=12 ; angka2=12; angka1=12;
              break; }
       case 9 :{ angka4=13; angka3=12 ; angka2=12; angka1=12;
              break; }
       case 10 :{ angka4=14; angka3=12 ; angka2=12; angka1=12;
              break; }
       case 11 :{ angka4=14; angka3=13 ; angka2=12; angka1=12;
              break; }
       case 12 :{ angka4=14; angka3=14 ; angka2=12; angka1=12;
              break; }
       case 13 :{ angka4=14; angka3=14 ; angka2=13; angka1=12;
              break; }
       case 14 :{ angka4=14; angka3=14 ; angka2=14; angka1=12;
              break; }
       case 15 :{ angka4=14; angka3=14 ; angka2=14; angka1=13;
              break; }
       case 16 :{ angka4=14; angka3=14 ; angka2=14; angka1=14;
              break; }
       default :{ angka4=14; angka3=14 ; angka2=14; angka1=14;
              break; }
         }

}



>>>INISIALISASI COUNTER<<

Counter 0 adalah counter 8 bit, sedangkan Counter 1 adalah 16 bit. Silahkan membaca terlebih dahulu penjelasan mengenai counter dan timer disini.

void init_ctr(void) //COUNTER 0 8 BIT untuk pindah kolom 7 segmen
{
  
   
   TCCR0A |= (1 << WGM01); // Configure timer 0 for CTC mode
   TIMSK |= (1 << OCIE0A); // Enable CTC interrupt
   OCR0A   = 50; // Set CTC compare value  till blink disapear at 1MHz AVR clock, with a prescaler of 64
   TCCR0B |= (1 << CS01)|(1 << CS00); // Start timer at Fcpu/64
   
   
}


void init_ctr1(void) //COUNTER 1 untuk penghitung pulsa saat 600ms
{
   
   TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
   TIMSK |= (1 << OCIE1A); // Enable CTC interrupt 
   OCR1A  = 586; //compare the CTC A = 600ms =586
   TCCR1B |= ((1 << CS10) | (1 << CS12)); // Start timer at Fcpu/1024

}




>>>INTERRUPT TIMER<<


ISR(TIMER1_COMPA_vect) //interrupt timer 1 (16 bit)  untuk capture jumlah pulsa 

{ uint16_t rpm,anime; //variabel

anime=0;
rpm=0;

switch(kalibrasi) {  //Pemilih kalibrasi
      case 1 :{ 
          rpm=number/100;
    break; }

      case 2 :{ 
          rpm=number/10;
    break; }

      case 3 :{ 
          rpm=number;
    break; }

      case 4 :{ 
          rpm=number*10;
    break; }

      case 5 :{ 
          rpm=number*100;
    break; }
      
   case 6 :{ 
          anime=1;
    break; }
      
   case 7 :{ 
          anime=2;
    break; }

    }

  //Pemilih antara angka rpm atau animasi level
switch(anime) { 

case 0 : { //ANGKA RPM

OCR1A  = 586;
angka1 = rpm%10;

if(rpm>9) angka2 = ((rpm%100) - (rpm%10)) /10 ;
else angka2=10;

if(rpm>99) angka3 = ((rpm%1000) - (rpm%100)) /100 ;
else angka3=10;

if(rpm>999) angka4 = ((rpm%10000) - (rpm%1000)) /1000 ;
else angka4=10;
  
break ; }

case 1 : {  //ANIMASI MODE 1
OCR1A  = 100;
animasi(number/10);
  
break ; }
         
case 2 : {  //ANIMASI MODE 2
OCR1A  = 100;
animasi(number/50);

break ; }

  }


number=0;

}

ISR(TIMER0_COMPA_vect) // timer 0 (8 bit) untuk pindah kolom 7 segmen
{

//tiap segmen yg akan dinyalakan akan diberikan logic High

segstep++;

  switch(segstep) {  
      case 1 :{  conv_segmen(10);
              PORTD |= _BV(PD0);
                 PORTD &= ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5)  ;  
                    conv_segmen(angka4);
     break;
                  }
 
         case 2 :{  conv_segmen(10);
              PORTD |= _BV(PD1);
                 PORTD &= ~_BV(PD0) & ~_BV(PD4) & ~_BV(PD5)  ;  
                    conv_segmen(angka3);
     break;
                  }
         case 3 :{  conv_segmen(10);
              PORTD |= _BV(PD4);
                 PORTD &= ~_BV(PD1) & ~_BV(PD0) & ~_BV(PD5)  ;  
                    conv_segmen(angka2);
     break;
                  }
         case 4 :{  conv_segmen(10);
              PORTD |= _BV(PD5);
                 PORTD &= ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD0)  ;  
                    conv_segmen(angka1);
     segstep=0;
     break; 
         }

                 }


}


>>>COUNTER INTERRUPT dari BUSI<<

SIGNAL (SIG_INT0) //INTERRUPT 0 menghitung pulsa dari radiasi CDI vs BUSI
{
number++;

}



>>>TOMBOL<<

void tombol(void)
{


if(bit_is_clear(PIND, PIND3)) //pembacaan pada pin D3

{ valid++;  //validasi penekanan
_delay_ms(10);
}

if( valid >= 50) //jika melebihi noise motor/getaran, ubah suai nilai ini
{ 

valid=0;
kalibrasi++; //ubah kalibrasi



if (kalibrasi >= 8) kalibrasi=1;

conv_segmen(10);


//Menulis nilai kalibrasi ke EEPROM 
eeprom_write_byte((uint8_t*)20, kalibrasi); 
_delay_ms(500);


  }
}


>>>MEMBACA EEPROM  nilai KALIBRASI<<

void baca_eeprom(void)
{

kalibrasi = eeprom_read_byte((uint8_t*)20);

if(kalibrasi == 0xFF) kalibrasi=3;


}



>>>MAIN PROGRAM<<

int main(void)
{

//Inisialisasi Interrupt
        GIMSK |= (1<<INT0) ; // inetrupt untuk hitung pulsa busi
   MCUCR |= (1<<ISC01)| (1<<ISC11); //fall edge 
//Inisialisasi PIN ATTINY2313 
 DDRD |= _BV(PD0) | _BV(PD1) | _BV(PD4) | _BV(PD5)  ; // segmen select / common scans
 DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) ; // seg a,b,c,d,e,f,g
    
 DDRD &= ~_BV(PD3) ; // Input kalibrasi

init_ctr(); //hidupkan COUNTER0
sei();

_delay_ms(1000);


//tampilan kata ke 2, sesuaikan dengan kebutuhan atau hapus jika tidak mau

angka1=16 ;
angka2=1 ;
angka3=19 ;
angka4=18 ;


_delay_ms(1000);

init_ctr1(); //hidupkan COUNTER 1

baca_eeprom(); // baca nilai kalibrasi 



//muter terussssss
while(1)

{
tombol();

}


}




videonya....seperti dibawah ini





tips: Tegangan pada lampu depan/ langsung dari coil bisa berlebih jika akimu rusak/habis. Jadi usahakan mencari sumber tegangan yg tidak merusak regulator 7805


 Selamat Mencoba
Share:

Rabu, 27 November 2013

[Script Breakdown] Bikin Jam Di Televisi

Untuk melanjutkan ke project berikut ini disarankan agar menuju ke pembahasan awal mengenai Microcontroller VS Televisi di sini : Part#1 Part#2 Part#3 dan Pakman 







Siapkan Bahan-bahan berikut ini:


  1. Micro-AVR ATTiny 2313
  2. Breadboard
  3. Power suply 5v , atau adaptor 12v dan diregulasi 7805
  4. Resistor 10K, 470
  5. Tombol push button 2 buah
  6.  Xtal 20Mhz + capasitor 22pF
  7. Programer AVR + header isp (2 x 10)
  8. Pesawat TV yg nganggur (pastikan tidak bentrok dengan jadwal mama nonton tv)

Kemudian skematik yg digunakan seperti gambar berikut :


Klik pada gambar buat memperjelas gambar
*) Rangkaian sama persis dengan project pakman hanya tombol yg digunakan  berada pada INT0 dan INT1


Kita akan breakdown scriptnya secara satu persatu agar pembaca semakin mengerti (atau tambah mumet .....mungkin looo). SIlahkan Baca Penjelasan disela-sela script.

>>> Header <<

#define F_CPU 20000000UL  //Frekuensi xtal yg digunakan, ubah fusebit untuk mengaktifkan
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>


#define FONTHEIGHT 12 //Tinggi font yg diwakili lebar array font

#define HSYNC PORTB=0; //PORTB=0 sebagai bit sinkronisasi horizontal atau penghasil 0 volt
#define BLACK PORTB=1;//PORTB=0 sebagai warna putih
//Berikut ini rumus untuk menampilkan warna dot putih di televisi berdasarkan array
#define COL(r) textnya=word[r][fontzoom];

static uint8_t fontline = 0; //variabel fontline
static uint8_t fontzoom = 0; //variabel zoom font untuk besar karakter yg ditampilkan

//BERIKUT INI ARRAY DOT YG MEWAKILI ANGKA 0 - 9 :
const unsigned char font[12][FONTHEIGHT] PROGMEM = { 
   {    //0
 0b00000000,
 0b01111100,
 0b11000110,
 0b11001110,
 0b11011110,
 0b11010110,
 0b11110110,
 0b11100110,
 0b11000110,
 0b01111100,
 0b00000000,
 0b00000000,
 },
 {//1
 0b00000000,
 0b00010000,
 0b00110000,
 0b11110000,
 0b00110000,
 0b00110000,
 0b00110000,
 0b00110000,
 0b00110000,
 0b11111100,
 0b00000000,
 0b00000000,
 },
 {//2
 0b00000000,
 0b01111000,
 0b11001100,
 0b11001100,
 0b00001100,
 0b00011000,
 0b00110000,
 0b01100000,
 0b11001100,
 0b11111100,
 0b00000000,
 0b00000000,
 },
 {//3
 0b00000000,
 0b01111000,
 0b11001100,
 0b00001100,
 0b00001100,
 0b00111000,
 0b00001100,
 0b00001100,
 0b11001100,
 0b01111000,
 0b00000000,
 0b00000000,
 },
 {//4
 0b00000000,
 0b00001100,
 0b00011100,
 0b00111100,
 0b01101100,
 0b11001100,
 0b11111110,
 0b00001100,
 0b00001100,
 0b00011110,
 0b00000000,
 0b00000000,
 },
 {//5
 0b00000000,
 0b11111100,
 0b11000000,
 0b11000000,
 0b11000000,
 0b11111000,
 0b00001100,
 0b00001100,
 0b11001100,
 0b01111000,
 0b00000000,
 0b00000000,
 },
 {//6
 0b00000000,
 0b00111000,
 0b01100000,
 0b11000000,
 0b11000000,
 0b11111000,
 0b11001100,
 0b11001100,
 0b11001100,
 0b01111000,
 0b00000000,
 0b00000000,
 },
 {//7
 0b00000000,
 0b11111110,
 0b11000110,
 0b11000110,
 0b00000110,
 0b00001100,
 0b00011000,
 0b00110000,
 0b00110000,
 0b00110000,
 0b00000000,
 0b00000000,
 },
 {//8
 0b00000000,
 0b01111000,
 0b11001100,
 0b11001100,
 0b11101100,
 0b01111000,
 0b11011100,
 0b11001100,
 0b11001100,
 0b01111000,
 0b00000000,
 0b00000000,
 },
 {//9
 0b00000000,
 0b01111000,
 0b11001100,
 0b11001100,
 0b11001100,
 0b01111100,
 0b00011000,
 0b00011000,
 0b00110000,
 0b01110000,
 0b00000000,
 0b00000000,
 },
 {//:
 0b00000000,
 0b00000000,
 0b00000000,
 0b00110000,
 0b00110000,
 0b00000000,
 0b00000000,
 0b00110000,
 0b00110000,
 0b00000000,
 0b00000000,
 0b00000000,
 },
 {//blank
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 0b00000000,
 }};



uint8_t word[7][12]; //array dari dot

int tick; //variabel untuk mendapatkan pulse tiap sync

uint8_t jam,menit,detik,textnya;//variabel jam dan text





>>> TIMER <<

void timer_init(void){ //timer untuk menentukan pewaktu Hsync 64us

 TCCR1B |= (1<<WGM12);
 TIMSK |= (1<<OCIE1A);
 OCR1A = 1280; //64 (us)* 20(Mhz) sesuaikan dengan xtal yg dipakai
 TCCR1B |= (1<<CS10);
}





>>>GESER PER PIXEL <<

void geser(void)
{ uint8_t a;

//loop untuk menggeser Array angka yg ditampilkan dalam 64 us
for(a=0;a<8;a++){ 
PORTB = (textnya & 0x81) + 1;
textnya <<=1;
 asm("nop");
 asm("nop");
 asm("nop");
//sesuaikan banyak asm("nop"); dengan lebar karakter yg diinginkan
}






>>>TIMER INTERRUPT dan RASTER <<

/* Timer interrupt */

ISR (TIMER1_COMPA_vect) { //64 us
 static uint16_t rasterline=0;
 

 HSYNC; //mulai h sync
        //tulis jika diantara line 100 dan 160  
 if( rasterline > 100 && rasterline <= 160 ) {
  _delay_us(4);
  BLACK;
  _delay_us(8);
        asm("nop");
        asm("nop");
        asm("nop");

       //tampilkan dot putih(1) atau hitam(0)sesuai array gambar angka
    COL(0); //tampilkan puluhan jam
    geser();
    COL(1); //tampilkan satuan jam
    geser();
    COL(2); //tampilkan :
    geser();
    COL(3);//tampilkan puluhan menit
    geser();
    COL(4);//tampilkan satuan menit
    geser();
    COL(2);//tampilkan :
    geser();
    COL(5);//tampilkan puluhan detik
    geser();
    COL(6);//tampilkan satuan detik
    geser();
  
  fontline++; //tambahkan line / pindah raster selanjutnya
  if(fontline % 6 ==0)fontzoom++; 
// ubah angka 6 untuk mengatur tinggi karakter yg tampil di tv , fontzoom menyatakan berapa jumlah line raster yg akan ditampilkan (sama) sebelum menuju ke array baris karakter selanjutnya. semakin lama ditampilkan maka karakter akan semakin memanjang. sesuaikan nilai if di atas (  if( rasterline > 100 && rasterline <= 160 )  )


 } 

 //yang ini bagian Vertical sync, hanya menggunakan raster genap saja,  karena efek kelembaban mata tidak perlu menampilkan karakter saat raster ganjil (menghemat memory)
 else if( rasterline >= 0 && rasterline < 5 ) {
  _delay_us(27);
  BLACK;
  _delay_us(5);
  HSYNC;
  _delay_us(27);
  BLACK;
 } else if( (rasterline >= 5 && rasterline <= 10) ) {
  _delay_us(2);
  BLACK;
  _delay_us(28);
  HSYNC;
  _delay_us(2);
  BLACK;
 } else if( rasterline >311-6 ) {
  _delay_us(2);
  BLACK;
  _delay_us(28);
  HSYNC;
  _delay_us(2);
  BLACK;
 } else { //yang ini mereset nilai array karakter
  _delay_us(3);
  BLACK;
   fontline = -1;
  fontzoom=0;
   }

 rasterline++;
 //bagian dibawah ketika layar ga tampil maka pindahkan nilai waktu
 if( rasterline > 311 )
   { rasterline = 0;
   

   memcpy_P(&word[0],&font[jam/10],12);
   memcpy_P(&word[1],&font[jam%10],12);
   memcpy_P(&word[2],&font[10],12);
   memcpy_P(&word[3],&font[menit/10],12);
   memcpy_P(&word[4],&font[menit%10],12);
   memcpy_P(&word[5],&font[detik/10],12);
   memcpy_P(&word[6],&font[detik%10],12);
 
      }


//yang ini mengakali nilai 1 detik , karena resource timer  termakan oleh proses sinkronisasi
  tick++;

    if(tick == 15625){ //ubah nilai tick sehingga pas 1 detik
    tick=0;
       detik++;
    if(detik==60){
      menit++;
   detik=0;}

       if(menit==60){
    menit=0;
    jam++;}
    if (jam==24) jam=0;
    }
}





>>>TOMBOL <<

SIGNAL (SIG_INT0)  //Tombol Tambah Jam
{
jam++;

if(jam == 24) jam=0;

detik=0;
}

SIGNAL (SIG_INT1)// Tombol Tambah Menit
{
menit++;  

if(menit == 60) menit =0;


detik=0;
}







>>>MAIN PROGRAM <<

int main() {
tick=0;
jam=00;
menit=00;
detik=00;

 
 
 
 MCUCR |= (1<<ISC01)  |(1<<ISC11) ; // interupt tombol fall edge

 GIMSK |= (1<<INT0) |(1<<INT1); //aktifkan interrupt 0 dan 1

 DDRB = (1<<PB7)|(1<<PB0); //PB0=1K, PB7=470 ohm

 timer_init(); //hidupkan timer
 sei(); // aktifkan interrupt

 for( ;; ); //muter terussssss
}





>>>HASILNYA <<





SELAMAT MENCOBA
Share:

Selasa, 01 Januari 2013

Script Break Down - Episode Love Hurt






SELAMAT TAHUN BARU 2013 kepada para pembaca setia blog tercinta. Dengan semangat baru di tahun yang baru ini kita mulai dengan pembahasan script-script yang terdapat di blog ini karena ada beberapa teman yang merasa "terintimidasi" dengan bahasa pemrograman yang dianggap terlalu susah. 

Kali ini kita akan membahas script dari percobaan led matriks  "love hurt" yang ditulis agustus 2011. Project love hurt ini juga terdapat dalam paket belajar dasar microcontroller  yang dapat anda pesan dengan harga yang cukup terjangkau oleh  kantong anak SMA sekalipun.

Seperti pada posting led matrix love hurt rangkaian yang digunakan seperti skematik berikut ini :



Rangkaian nya sangat simple, sesimple scriptnya juga dan marilah kita break down scriptnya


HEADER


#define F_CPU 1000000UL
#include < avr/io.h >
#include < util/delay.h >
#include < avr/pgmspace.h >
#include < string.h >
#include < avr/eeprom.h >

Pada penjelasan terdahulu mengenai dasar-dasar bahasa GCC maka dapat dilihat pada header terdapat inisialisai dari beberapa parameter. Yang pertama adalah #define F_CPU yang menjelaskan clock microcontroller yang digunakan. Berdasarkan skematik rangkaian dapat dilihat jika microcontroller attiny2313 yang dipakai tanpa menggunakan xtal sehingga dapat dikatakan memakai internal clock (Calibrated RC Oscillator). Secara default ketika ic attiny2313 keluar dari pabrik memiliki clock internal 8MHz dengan pembagian CLKDIV8=ON yang berarti clock dibagi 8 sehingga menghasilkan angka 1MHz. Untuk melihat clock yang dipakai dapat dilihat pada pembacaan fusebit, dapat dilakukan melalui menu programming pada AVRSTUDIO.

  
Image Hosted by PicturePush - Photo Sharing


Selanjutnya didalam header dituliskan beberapa include yang berguna dalam script love hurt seperti definisi kaki micro (io.h) ,delay.h sebagai pengatur delay waktu, pgmspace.h sebagai trick memanfaatkan flash memory sebagai static ram, string.h sebagai pengolah data berupa string dan eeprom.h yang memudahkan penulisan script untuk akses eeprom (memory non-volatile / tidak hilang saat micro tanpa power) .


DEFINISI VARIABEL , RAM & EEPROM


//Progmem simpannya di FLASH memory

const char love1[] PROGMEM =
{
0b0011110,
0b0100001,
0b1000010,
0b0100001,
0b0011110

};

const char love2[] PROGMEM =
{
0b0001100,
0b0010010,
0b0100100,
0b0010010,
0b0001100

};

const char L[] PROGMEM ={0x7f, 0x7f, 0x40, 0x40, 0x20};
const char O[] PROGMEM ={0x3e, 0x7f, 0x41, 0x41, 0x3e};
const char V[] PROGMEM ={0x3f, 0x7e, 0x40, 0x20, 0x1f};
const char E[] PROGMEM ={0x7f, 0x7f, 0x49, 0x49, 0x41};
const char H[] PROGMEM ={0x7f, 0x7f, 0x08, 0x08, 0x7f};
const char U[] PROGMEM ={0x3f, 0x7f, 0x40, 0x40, 0x3f};
const char R[] PROGMEM ={0x7f, 0x7f, 0x11, 0x29, 0x46};
const char T[] PROGMEM ={0x03, 0x03, 0x7f, 0x03, 0x02};

const char creature[]={0x4e, 0x31, 0x35, 0x31, 0x4e}; //simpan di memory/RAM aja

uint8_t EEMEM tengkorak[5]= {0x1e, 0x75, 0x61, 0x75, 0x1e}; //simpan di EEPROM

uint8_t EEMEM pacman[5]= {0x26, 0x67, 0x67, 0x7f, 0x3e}; //simpan di EEPROM


char dotnya[5],scrolnya[7];



Untuk mengetahui angka hexa yang terdapat dalam array ada lebih baiknya terlebih dahulu membuka software generator dot matrix yang dapat dilihat disini.

Pada penulisan array diatas ada 3 type yang dipergunakan yaitu RAM, PROGMEM dan EEMEM. Kenapa mesti seperti ini ya karena dikarenakan attiny2313 yang memiliki kapasitas RAM yang super irit yaitu 128byte saja, sehingga untuk menambah memory maka kita manfaatkan memory flash (program) yang cukup lumayan 2048byte atau 2Kbyte (ini aja masih kecil banget). Untuk memanfaatkan flash diperlukan inisialisasi tambahan berupa PROGMEM dan tidak bisa dipakai langsung seperti halnya jika ditempatkan pada RAM umum, harus ada proses memindahkan flash PROGMEM menuju memory RAM. Tentunya tidak semuanya tapi yang akan diolah saja yang dipindahkan. Pada inisialisasi variabel array diatas terdapat 2 buah array RAM yaitu dotnya[5] dan scrolnya[7] yang akan ditimpa dengan isi PROGMEM jika dibutuhkan.

Pada project lovehurt diperlihatkan juga cara mengakses memory EEPROM dengan inisialisai berupa EEMEM. Tujuan menggunakan memory EEPROM adalah sifatnya yang tidak terhapus jika baterai atau power dimatikan (non-volatile memory)


BAGIAN MENULIS KE LED MATRIX

void tulis(uint8_t lama)
{
  uint8_t a,b;

for(a=0 ; a<lama ; a++)
   {
   for(b=0 ; b<5 ; b++)     
  {
         PORTB = ~(1<<b) ;
         PORTD = dotnya[b];
                _delay_ms(2);
  }

   }
}


void geser(uint8_t lama)
{
  uint8_t a,b;
   for(a=0 ; a<11 ; a++)     
    {
    if( a<6) 
      { 
                for(b=0 ; b<(5-a) ; b++)  dotnya[b]=0x80;
                for(b=(5-a); b<5 ;b++) dotnya[b]=scrolnya[b-5+a];
     
                tulis(10);
        }
    else if (a==6) tulis(lama);

    else 
       {        for(b=0 ; b<11-a ; b++) dotnya[b]=scrolnya[a-5+b];
                for(b=(11-a); b<11 ;b++) dotnya[b]=0x80;  
      
                tulis(10);
       }     
     }  
}

void naik (uint8_t lama)

{ uint8_t q,step=0;
  
  
  while(step!=16)
   {
 if( step <8)
    {   
                for(q=0 ; q < 5 ; q++) dotnya[q] = scrolnya[q] << (7 - step) ; 

                tulis(10);
           } 
   
        else if (step == 8)
           {    
             tulis(lama); 
    
           }      
 else 
    {   
              for(q=0 ; q < 5 ; q++)  dotnya[q] = scrolnya[q] >> (step - 7) ;  
          
              tulis(10);
     } 
        step++; 
   }    
}

}

Nah inilah bagian utama dari penggerak tulisan geser kiri atau naik. Perhatikan pertama bagian function tulis dimana terdapat isian variabel lama yang berarti lama looping dieksekusi yang akan menentukan lama tulisan ditampilkan. Begitu pula jika ingin menggeser maka variabel lama perlu dimasukkan untuk menentukan lama nya teks diam setelah digeser.

Bagaimana sih cara menghidupkan dotmatrix ? sebaiknya baca penjelasannya disini . Jadi pada intinya nilai hexa yang diinisialisaikan pada array diawal berjumlah 5 buah array. Sedangkan bit yang digunakan adalah 7 bit karena memang dot matrix yang dgunakan bertype 5x7 (5 kolom  x 7 baris) . Perhatikan loop berikut :


 for(b=0 ; b<5 ; b++)

{
PORTB = ~(1<<b) ;
PORTD = dotnya[b];
                 _delay_ms(2);
}


Skematik menunjukkan bahwa kolom di kontrol oleh port B0 - B3 dan baris dikontrol oleh port D0 - D6. Loop diatas menunjukkan proses geser kolom (scanning) dengan perintah PORTB = ~(1<<b)  yang artinya angka 1(biner) digeser ke sebelah kiri  sebanyak dari nilai b kemudian dinegasi .  Variabel b mengontrol pergeseran berdasarkan loop. Jika kolom dot matrix '0' akan menyebabkan LED pada baris yang mendapat bit '1' menyala. Hal ini dapat dikatakan kolom aktif LOW dan baris aktif HIGH. Urutan loop dari scanning pada PORTB seperti berikut (11110) , (11101) ,(11011) ,(10111) ,(01111).

Ingat penjelasan terdahulu bahwa array yang ada pada flash (PROGMEM) atau EEPROM harus dipindahkan kedalam array memori RAM  dotnya[b]. Sekali lagi variabel b berperan dalam menentukan array baris yang sesuai dengan kolom yang sedang aktif atau mendapat scanning "LOW" (0).

Untuk proses geser ke kiri dan geser keatas ada sebuah variabel yaitu step yang berfungsi sebagai penanda posisi pergeseran yang sedang tampil sehingga text yang tampil pada dot matrix memiliki efek bergeser. Selebihnya yang diperlukan hanya proses kreatif mengeser-geser bit dari baris berdasarkan loop yang sedang berjalan dan dipindahkan ke array scrolnya[ ].


MAIN PROGRAM



int main(void)
{
 DDRD = 0b1111111; // untuk baris
 DDRB = 0b11111;  // untuk kolom

 PORTD =0; // Set all pins low
 PORTB =0b11111; //matikan layar
    
    
 
 
 while(1)
 {
    // yang ini nulis langsung 
  
     strncpy_P(dotnya,love2,5);
     tulis(20);
     strncpy_P(dotnya,love1,5);
     tulis(40);
     strncpy_P(dotnya,love2,5);
     tulis(20);
     strncpy_P(dotnya,love1,5);
     tulis(40);
     strncpy_P(dotnya,love2,5);
     tulis(20);
     strncpy_P(dotnya,love1,5);
     tulis(40);     

//yang ini pake function geser 

     strncpy_P(scrolnya,L,5);
     geser(50);
     strncpy_P(scrolnya,O,5);
     geser(50);
     strncpy_P(scrolnya,V,5);
     geser(50);
     strncpy_P(scrolnya,E,5);
     geser(50);
     strncpy_P(scrolnya,H,5);
     geser(50);
     strncpy_P(scrolnya,U,5);
     geser(50);
     strncpy_P(scrolnya,R,5);
     geser(50); 
     strncpy_P(scrolnya,T,5);
     geser(50); 

//geser ambil dari RAM
 
     strncpy(scrolnya,creature,5);  //tanpa _P karena ambil di RAM
     naik(50); 
 
//ambil dari eeprom ..mengirit..

     eeprom_read_block((void*)&scrolnya,(const void*)&tengkorak, 5); 
     naik(50);

     eeprom_read_block((void*)&scrolnya,(const void*)&pacman, 5); 
     geser(50);

   }
 
 return 0;
}



Pada bagian awal dari function main( ) terdapat inisialisai port dari attiny yang digunakan yaitu PORTB dan PORTD yang kesemuanya diberi bit 1 yang artinya port tersebut dipakai sebagai port output.

Script yang digunakan untuk memindahkan memory flash (PROGMEM) menuju RAM adalah  operasi string strncpy_P, ingat array dari char (8byte) dapat dianggap sebagai string,   seperti contoh  strncpy_P(dotnya,love2,5)  yang artinya isi dari array dotnya[ ] diisi dengan array dari array PROGMEM love2. Jika diambil dari RAM langsung maka operasi copy ini menggunakan strncpy( ) tanpa _P.

Untuk pemindahan isi dari EEPROM menuju RAM menggunakan syntax eeprom_read_block ( *pointer_ram_tujuan, *posisi_memori_eeprom, jumlah blok ), seperti contoh  eeprom_read_block((void*)&scrolnya,(const void*)&tengkorak, 5). Jangan dipusingkan dengan void dan * (pointer) karena itu hanya atribut yang menyatakan type data diabaikan.


MUDAH BUKAN ? jika ada pertanyaan atau request script break down yang lain akan saya bahas dengan senang hati.


SELAMAT TAHUN BARU 2013 KAWAN



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