Pengukuran kecepatan objek (dua arah) dengan Arduino dan photo dioda menggunakan metode interupsi serta timer

Manfaat mengukur kecepatan benda menggunakan arduino antara lain : pengukuran laju kendaraan/mobil, mencari kecepatan bandul, menentukan kecepatan benda jatuh, mengukur laju pukulan dan lain-lain.

Prinsip kerja menentukan kecepatan benda pada arduino adalah mendeteksi objek melewati dua sensor photodioda yang disinari dengan infra merah dari LED dengan jarak yang diketahui. Ketika sebuah objek melewati photodioda dan menghalangi sinar sumbernya, maka photodioda akan memberikan sinyal aktif ke arduino melalui jalur interupsi sebagai nilai awal, demikian pula ketika objek melewati photodioda kedua yang disimpan sebagai nilai akhir. Pembagian antara jarak sensor dengan waktu ini akan diperoleh kecepatan.

Pengukuran kecepatan dengan arduino (dalam meter/detik atau km/jam) mengharuskan perhitungan waktu yang efektif guna memperoleh hasil pengukuran yang akurat. Kesalahan 1 mili detik saja akan menghasilkan perbedaan kecepatan yang cukup jauh. untuk mengurangi resiko ini bisa dilakukan dengan menambah jarak sensor.

berikut skema perancangan mencari kecepatan objek dengan arduino:

catatan: photodioda dipasang terbalik (plus ke ground dan minus ke pin Arduino pullup) agar menghasilkan output berupa digital signifikan.

program atau sketch menentukan kecepatan benda menggunakan arduino :

#define sensor1 2
#define sensor2 3
#define jarakSensor 0.05 //meter
#define waktuTick 1/8000000 //detik
#define mpsKekmph 3.6

volatile uint16_t waktuA;
volatile uint16_t waktuB;
volatile uint16_t overflowTimer;
volatile bool dariA;
volatile bool dariB;
volatile bool sampaiA;
volatile bool sampaiB;
double Kecepatan;

void setup() {
  Serial.begin(9600);
  Serial.println("Pengukuran kecepatan objek (dua arah) dengan Arduino");
  Serial.println("dan photo dioda menggunakan metode interupsi serta timer");
  Serial.println("https://www.project.semesin.com");

  pinMode(sensor1, INPUT_PULLUP);
  pinMode(sensor2, INPUT_PULLUP);
  
  EIFR |= _BV(INTF1) |_BV(INTF0);
  TIMSK1 |= _BV(TOIE1);
  TCCR1A = 0;

  attachInterrupt(digitalPinToInterrupt(sensor1), objekMelewatiA, RISING);
  attachInterrupt(digitalPinToInterrupt(sensor2), objekMelewatiB, RISING);
}

void loop() {
  if(dariA && sampaiB)
  {
    Kecepatan = 1.0 * jarakSensor / ((double)waktuTick * ((uint32_t)waktuB + (overflowTimer * 65535)));
    Serial.print("Kecepatan = ");
    printDouble(Kecepatan, 6);
    Serial.print(" meter/detik (");
    printDouble(Kecepatan * mpsKekmph, 6);
    Serial.println(" km/jam) dari A ke B");
    dariA = false;  
    sampaiB = false;  
  }
  else if(dariB && sampaiA)
  {
    Kecepatan = 1.0 * jarakSensor / ((double)waktuTick * ((uint32_t)waktuA + (overflowTimer * 65535)));
    Serial.print("Kecepatan = ");
    printDouble(Kecepatan, 6);
    Serial.print(" meter/detik (");
    printDouble(Kecepatan * mpsKekmph, 6);
    Serial.println(" km/jam) dari B ke A");
    dariB = false;  
    sampaiA = false;  
  }
  else if(dariA || dariB)
  {
    if(overflowTimer > 5000)
    {
      dariA = false;
      dariB = false;
      TCCR1B = 0;
      Serial.println("Terlalu lambat");
    }
  }
}

void objekMelewatiA()
{
  if(dariB)
  {
    waktuA = TCNT1;
    TCCR1B = 0;
    sampaiA = true;
  }
  else
  {
    TCNT1 = 0;
    TCCR1B = _BV(CS10);
    TIFR1 |= _BV(TOV1);
    overflowTimer = 0;
    dariA = true;
  }
}
void objekMelewatiB()
{
  if(dariA)
  {
    waktuB = TCNT1;
    TCCR1B = 0;
    sampaiB = true;
  }
  else
  {
    TCNT1 = 0;
    TCCR1B = _BV(CS10);
    TIFR1 |= _BV(TOV1);
    overflowTimer = 0;
    dariB = true;
  }
}

ISR(TIMER1_OVF_vect)
{
  overflowTimer++;
}

void printDouble(double nilai, byte belakangKoma)
{
  if(nilai < 0.0)
  {
    Serial.print('-');
    nilai = -nilai;
  }
  
  Serial.print ((long)nilai);
  if( belakangKoma > 0) 
  {
    Serial.print(".");
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = belakangKoma - 1;
    while(belakangKoma--)
    {
      mult *=10;
    }
    if(nilai >= 0)
    {
      frac = (nilai - int(nilai)) * mult;
    }
    else
    {
      frac = (int(nilai)- nilai ) * mult;
    }
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
    {
      padding--;
    }
    while(  padding--)
    {
      Serial.print("0");
    }
    Serial.print(frac,DEC) ;
 }
}