Exploring STC 8051 Microcontrollers – Coding

Using PCA to Measure Pulse Width from HCSR-04 SONAR Module

Apart from frequency measurement, we can apply the same input capture technique to measure pulse widths or PWM duty cycles. Pulse width measurement requires capturing PCA counts of two successive opposite edges unlike two successive same edges. In this segment, we will see how we can measure distance measured by a HCSR-04 SONAR sensor by measuring pulse width output from it.

Code

 #include "STC8xxx.h"
#include "BSP.h"
#include "LCD.c"
#include "lcd_print.c"
 
unsigned char state = 0x00;
unsigned int pulse_width = 0x0000;
 
void setup(void);
 
void PCA_ISR(void)          
interrupt 7
{   
  if(check_PCA_0_flag)
  {
    state ^= 1;
    clear_PCA_0_flag;
  }
  
  switch(state)
  {
    case 1:
    {
      PCA_load_counter(0x0000);
      break;    
    }
    
    default:
    {  
      pulse_width = PCA_get_CCAP0();
      break;
    }
  }
}
 
void main(void)
{
  float range = 0.0;
  
  setup();
 
  LCD_goto(0, 0); 
  LCD_putstr("Range/cm:"); 
  LCD_goto(0, 1); 
  LCD_putstr("Pulse/us:");  
 
  while(1)
  {
    P55_low;
    delay_ms(10);
    
    P16_high; 
    delay_us(10); 
    P16_low; 
    P55_high;
    
    range = ((((float)pulse_width) / 58.0)); 
    print_F(10, 0, range, 1); 
    print_I(10, 1, pulse_width);
    
    delay_ms(490);
  };
}
 
void setup(void)
{
  CLK_set_sys_clk(IRC_24M, 2, MCLK_SYSCLK_no_output, MCLK_out_P54);
 
  P16_push_pull_mode;
  P55_open_drain_mode;
  
  PCA_pin_option(0x00);
  
  PCA_setup(PCA_continue_counting_in_idle_mode, PCA_clk_sys_clk_div_12);
  PCA_load_counter(0x0000);
  
  PCA_0_mode(PCA_16_bit_both_edge_capture);
  
  _enable_PCA_0_interrupt;
  _enable_global_interrupt;  
  
  PCA_start_counter;
  
  LCD_init();
  LCD_clear_home();
}

Schematic

Explanation

HC-SR04 SONAR sensor works by sending a stream of ultrasonic pulses and then timing how long it took for an echo to bounce back from a nearby object. Based on timing, the sensor gives a pulse of variable width. The pulse width is a representation of distance or object range.

There are two pins apart from the power supply pins and these are needed to communicate with the sensor. When the trigger pin of the sensor is pulled high for about 10μs, the sensor acknowledges this short duration pulse as a command from its host micro to measure and return range data. A pulse output from the echo pin is the representation of distance.

Now let’s see how the code is working in this example. Firstly, the system clock is set to 12MHz.

 CLK_set_sys_clk(IRC_24M, 2, MCLK_SYSCLK_no_output, MCLK_out_P54); 

Pins P1.6 and P1.7 are tied to trigger and echo pins of HC-SR04 sensor respectively.

The PCA hardware is setup by setting its clock to 1MHz. Thus, each of PCA counter’s count is equal to 1μs tick. Default PCA pin configuration is used. The PCA counter is set to 0 count and 16-bit both edge capture mode is selected. Interrupt method is used and so PCA and global interrupts are enabled before starting the PCA counter. 

 PCA_pin_option(0x00);
  
PCA_setup(PCA_continue_counting_in_idle_mode, PCA_clk_sys_clk_div_12);
PCA_load_counter(0x0000);
  
PCA_0_mode(PCA_16_bit_both_edge_capture);
 
_enable_PCA_0_interrupt;
_enable_global_interrupt;  
  
PCA_start_counter;

The PCA hardware is now ready to detect edge transitions. When transitions occur, PCA interrupt is triggered. During a low-to-high transition or rising edge, the PCA counter is reset to 0 count and left to continue counting. Upon detecting a high-to-low transition or falling edge, the PCA counter is read.

 void PCA_ISR(void)          
interrupt 7
{   
  if(check_PCA_0_flag)
  {
    state ^= 1;
    clear_PCA_0_flag;
  }
  
  switch(state)
  {
    case 1:
    {
      PCA_load_counter(0x0000);
      break;    
    }
    
    default:
    {  
      pulse_width = PCA_get_CCAP0();
      break;
    }
  }
}

Since the PCA counter is counting with 1µs resolution, the falling edge capture count is the pulse width period in microseconds.

In the main loop, the SONAR sensor is triggered and the result from the PCA interrupt is processed. Target object distance detected by the sensor is a function of pulse width measured in microseconds. Thus, as per datasheet of the sensor, pulse width divided by 58 is equal to distance in centimeters.

The range and the captured pulse width are displayed in an LCD after performing the aforementioned computations.

 P55_low;
delay_ms(10);
    
P16_high; 
delay_us(10); 
P16_low; 
P55_high;
    
range = ((((float)pulse_width) / 58.0)); 
print_F(10, 0, range, 1); 
print_I(10, 1, pulse_width);
    
delay_ms(490);

Demo

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

Related Posts

13 comments

Leave a Reply

Your email address will not be published. Required fields are marked *