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)
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 !