PIC 16F877 dan Sensor Ultrasonik HC-SR04

Mengingat hasil pengukuran jarak yang dilakukan oleh HC-SR04 dilaporkan dalam bentuk lebar pulsa, maka mikrokontroler harus mengukur lebar pulsa tersebut secara akurat. Jarak hasil pengukuran (centimeter) sama dengan lebar pulsa (mikro detik) dibagi 58.1.HC-SR04 Ultrasonic Sensor

Dalam percobaan kali ini, digunakan mikrokontroler PIC16F877 dengan kristal 4 MHz.

Untuk mencapai tujuan tersebut, kita akan menggunakan TMR1 yang merupakan timer 16-bit. Dengan kristal 4 MHz, maka timer clock adalah 1 MHz atau timer resolution 1 us. Dalam hal ini kita tidak perlu mengatur prescaler (default prescaler 1:1).

void main()
{
  unsigned int pulseWidth;
  TRISB.F5 = 0;
  TRISB.F4 = 0;
  while(1) {
    PORTB.F5 = 1;
    delay_us(10);
    PORTB.F5 = 0;
    while( PORTB.F4 == 0 );
    TMR1H = 0x00;
    TMR1L = 0x00;
    TMR1ON_bit = 1; // INTCON.F0 = 1;
    while( PORTB.F4 == 1 );
    TMR1ON_bit = 0; // INTCON.F0 = 0;
    pulseWidth = (TMR1H << 8) | TMR1L;
    distance = pulseWidth / 58.1;
  }
}

PIC 16F877 memiliki fitur on-change interrupt pada pin RB4 – RB7. Kita bisa menerapkan kemampuan ini untuk mendeteksi perubahan logika pada pin RB4 (echo pin). Jadi, ketika terjadi interupsi yang dipicu oleh perubahan logika 0 ke 1, kita tempatkan perintah untuk meng-enable TMR1 pada ISR. Sementara ketika terjadi interupsi yang dipicu oleh perubahan logika dari 1 ke 0, kita tempatkan perintah untuk men-disable TMR1, membaca hasil cacahan dan meng-konversinya menjadi jarak.

int distance, pulseWidth;

void interrupt() 
{
  if ( INTCON.RBIF == 1 ) {
    INTCON.RBIE = 0;
    if ( PORTB.F4 == 1 )
      T1CON.F0 = 1;      // Start Timer, TMR1ON_bit = 1
    else if ( PORTB.F4 == 0 ) {
      T1CON.F0 = 0;      // Stop Timer, TMR1ON_bit = 0
      pulseWidth = (TMR1H << 8) | TMR1L;
      distance = pulseWidth / 58.1;
    }
  }
  INTCON.RBIF = 0;
  INTCON.RBIE = 1;
}

void main()
{
  char txt[7];
  TRISB.F5 = 0;
  TRISB.F4 = 1;
  INTCON.GIE = 1;   //Global Interrupt Enable
  INTCON.RBIF = 0;  //Clear PORTB On-Change Interrupt Flag
  INTCON.RBIE = 1;  //Enable PORTB On-Change Interrupt
  UART1_Init(9600);

  while(1)
  { 
    TMR1H = 0;                        
    TMR1L = 0;          
    distance = 0;
    PORTB.F5 = 1;                      
    Delay_us(10);                      
    PORTB.F5 = 0;                      
    delay_ms(500);   
    IntToStr(distance,txt);
    UART1_Write_Text(txt);      
  }
}