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<<
#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<<
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<<
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<<
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
Kalau mau pesen jadi brapa ya? soalnya gk bisa isi program
BalasHapus.. ato beli ic yg udah terprogram..saja berapa ya?
BalasHapusgabung di facebook com groups kumpulanskema saja gan.. lebih banyak temen temen kita riset bareng2.. :-)
belajar mrogram aja...ga rugi kok daripada ic lgsg pake
BalasHapusKlo indikatorny pk led bar & motorny injeksi bs g mas?
BalasHapuscz nyoba pk rpm meter yg dijual dipasaran kurang akurat cz jd krng 1/2 pembacaanny...
Injeksi mungkin lebih susah, dan seinget saya di system injeksi ada electronics nya yg bisa dibaca rpm nya, mungkin ke forum blog otomotif lebih bagus
BalasHapusAkurasi? Selama belum baca putaran mesin langsung atau tap di pulsa cdi secara langsung dijamin akurasi kurang ..
Mas saya bikin tachometer dari arduino..sistemnya sama,
BalasHapusTegangan Yg harus ke interupt itu apa harus 5 volt,biar logika high
Soalx pux saya kurang dari 5 volt,,
Mas saya bikin tachometer dari arduino..sistemnya sama,
BalasHapusTegangan Yg harus ke interupt itu apa harus 5 volt,biar logika high
Soalx pux saya kurang dari 5 volt,,
Mas nyoman, jika mau merubah menjadi 5digit apa yang perlu dirubah dari skripnya?
BalasHapusMas nyoman kalo 7 segmentnya di janti sma led scrip yang harus dirubah yang mana dan seperti apa.? Terimakasih
BalasHapusbagaimana kalau 7segmen diganti dengan LED
BalasHapusbisa dibaca pembahasannya disini : https://www.aisi555.com/2011/07/led-7-segmen.html
Hapus