Rabu, 29 Juni 2011

PENGHITUNG KECEPATAN MOTOR DC MENGGUNAKAN OPTOCOUPLER DENGAN CODEVISION AVR

Pada dasarnya aplikasi ini hampir sama dengan aplikasi penghitung frekuensi (Frequency Counter), dimana letak perbedaanya hanya pada perumusannya saja, dimana perumusan tersebut tergantung dari pengubahan detik ke menit dan banyaknya pulsa encoder dalam 1 putaran motor DC.

Jika menggunakan optocoupler sebagai sensor anda harus menggunakan rotary encoder yang di-couple dengan as motor dc untuk mendeteksi kecepatan putaran motor DC. Biasanya pada rotary encoder dibuat lubang-lubang sebagai representasi banyaknya pulsa. Dan anda harus menentukan terlebih dahulu banyaknya pendeteksian pulsa atau lubang pada rotary encoder untuk satu putaran yang dilakukan motor DC. Karena banyaknya pulsa atau lubang akan mempengaruhi perumusan perhitungan kecepatan motor DC dan semakin banyak pulsa atau lubang maka akan meningkatkan resolusi pembacaan kecepatan motor DC, dengan kata lain pembacaan kecepatan akan semakin presisi.

Dan jika motor DC anda sudah mempunyai internal encoder, anda hanya tinggal menghubungkan saja output internal encoder motor DC anda ke pin INT0 atau PD2.

Saya sendiri menggunakan rotary encoder sebanyak 20 lubang sehingga perumusan kecepatan motor DC menjadi:

pulsa=frekuensi*60/20; atau pulsa=frekuensi*30;

Dimana angka 60 digunakan untuk mengubah kedalam satuan RPM (round per minute), karena timer yang saya gunakan hanya membaca selama 1 detik, jika dikalikan sebanyak 60 maka akan menjadi 1 menit. Dan angka 20 adalah banyaknya lubang atau pulsa rotary encoder.

 

Jika teman-teman masih bingung mengenai fitur Timer dan Counter serta eksternal interupsi dapat membacanya pada menu Tutorial Timer dan Counter dan Interupsi Eksternal.

Berikut adalah listing program lengkapnya:

int frekuensi=0;
float pulsa;
char temp[8];

#include <mega16.h>
#include <lcd.h>
#include <delay.h>
#include <stdlib.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0×15 ;PORTC
#endasm


// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
frekuensi++;//baca frekuensi (pulssa) yg masuk ke INT0 trus di increament
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)//timer 1 detik untuk membaca pulsa yg masuk ke INT0
{
// Reinitialize Timer 1 value
    TCNT1H=0xD23A >> 8;
    TCNT1L=0xD23A & 0xff;
    pulsa=(float)frekuensi*60/20;//formula perhitungan kecepatan
    frekuensi=0;
    lcd_clear();
}

void tampilkan_LCD() //menampilkan data kecepatan di lcd
{
      lcd_gotoxy(0,0);
      lcd_putsf(“ElektrO-cOntrOl”);
      ftoa(pulsa,1,temp);
      lcd_gotoxy(0,1);
      lcd_puts(temp);
      lcd_gotoxy(0,5);
      lcd_putsf(“RPM”);
}

void main(void)
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 11.719 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0×00;
TCCR1B=0×05;
TCNT1H=0xD2;
TCNT1L=0x3A;
ICR1H=0×00;
ICR1L=0×00;
OCR1AH=0×00;
OCR1AL=0×00;
OCR1BH=0×00;
OCR1BL=0×00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: Off
// INT2: Off
GICR|=0×40;
MCUCR=0×02;
MCUCSR=0×00;
GIFR=0×40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0×04;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0×80;
SFIOR=0×00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm(“sei”)

while (1)
      {
      tampilkan_LCD();
      };
}

Jika ingin mendapatkan file program dalam bentuk CodeVision AVR silakan download link dibawah ini.

File program CodeVision AVR

Semoga bermanfaat…

10 komentar:

  1. simulasi proteusnya bagaimana??

    BalasHapus
  2. mmaf, saya tidak membuat simulasinya, karena saya coba langsung di hardware, klo mau simulasi, optocouplernya anda ganti dengan encoder yg berasal dari motor DC

    BalasHapus
  3. makasih atas postingan yang ini,,,, info ne sangat membantu saya,,, sklilagi makasih ya,,,
    oh ya aq mau nanyak gimana nyetting adc internal yang 16 bit ke mikro atmega lewat SPI

    BalasHapus
  4. maaf mas mau nanya, kalau misalnya motor dc nya cepet banget itu bakal kebaca presisi ngak sama optocouplernya, saya rencana mau membaca banyak garis di kertas transparan,, bakal spesifik ngak ya???

    BalasHapus
  5. bagaimana kalau sinyalnya dari Proximyty

    BalasHapus
  6. mas ada postingan tentang komunikasi spi??mohon bantuannya
    Balas

    BalasHapus
  7. salam kenal,moc 3021 fungsinya apa ya,setau saya moc3021 utk trigger triac,trus pin 1 moc kemana

    BalasHapus
  8. salam kenal, klu dengan arduino ingin menghitung pulsa untuk menentukan posisi
    list programnya seperti apa ya

    saya sudah coba dengan membuat program ini


    #include


    #include
    MegaServo servos;


    #define MIN_POS
    #define MAX_POS


    #define s0_pin 9
    int relayPin = 12;
    float pulse_pin=5,
    int id=1, arah;
    volatile int cacah;
    int count=0, count_temp=0;
    int waktu_cacah = 1;
    double rpm;
    volatile boolean state = false;

    int d0, temp_d0;
    int i;
    int d0_sh;
    char incomingString[6];

    float filtro = 1;


    void setup() {

    attachInterrupt(0, hitung, CHANGE);
    Serial.begin(9600);


    servos.attach(s0_pin);

    pinMode(relayPin, OUTPUT);
    pinMode(pulse_pin, INPUT);
    }

    void loop() {
    while (Serial.available() > 0) {

    int incomingByte = Serial.read();
    if(incomingByte==65)digitalWrite(relayPin,LOW);
    if(incomingByte==66)digitalWrite(relayPin,HIGH);
    if(incomingByte=='r')count=0;
    if(incomingByte==115){
    for(i=0;i<4;i++)incomingString[i] = Serial.read();
    temp_d0=d0;
    d0=atoi(incomingString);


    }
    }




    d0_sh = d0_sh * (1.0-filtro) + d0 * filtro;


    servos.write(d0_sh);


    if(d0>temp_d0)arah=1;
    if(d0<temp_d0)arah=2;
    if(digitalRead(pulse_pin)==HIGH&&id==1)
    {if(arah==1)count=count+5;
    if(arah==2)count=count-5;
    id=2;}
    if(digitalRead(pulse_pin)==LOW&&id==2){id=1;}
    Serial.println(count);
    delay(25);
    }
    void hitung() {
    cacah++;
    }

    tetapi hasil perhitungannya tidak sesuai
    masalahnya timbul saat motor diputar dengan kecepatan lebih, maka optocoupler tdk membaca sesuai jmlh encoder yg dibuat
    namun saat motor dibuat berputar lambat, maka bisa terbaca

    terima kasih
    mohon bantuannya dengan sangat

    BalasHapus
  9. optocoupler saya ganti hall effect sensor berhasil dengan baik, cuma masalah lcd nya aja yg agak cacad hehehehe...

    BalasHapus
  10. bisa jadi speedometer di sepeda motor nih,hehe..

    BalasHapus