Ultra Sonic Distance Meter

In this Project I used an ultra sonic sensor to display the distance of an object on a LCD display.

The system works by sending the sensor a 10uS ping to its trigger input then waiting for the receiving echo on its output. The distance of an object is proportional to the delay of the echo received and the length of the pulse received.

[/caption]

Show below is the part of code that:
1. Sends a ping to the sensor
2. Waits on the receiving echo while holding TMR2 to zero
3. Once the echo is received starts TMR2
4. When echo finishes sends back the value of TMR2.

int get_distance()
{
	_LATD2=1;			// set rd2 high
	__delay32(3000); 	// wait 100 uS
	_LATD2=0;			// then set back low
	while (_RD0==0);	// wait to receive pulse from sensor
	TMR2=0;				// reset TMR2
	while (_RD0==1);	// time TMR2
	return TMR2;		// return value of TMR2

Here is a diagram of the system:

ultrasonic

Here is my program code:


////////////////////////////////////////
// Robotics 3.1 Ultra Sonic Project.                                   
// Aron Horan 24/10/13                                                     
////////////////////////////////////////


#include <xc.h>
#include <libpic30.h>
#include <stdio.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

#define RS_PIN _LATC14
#define RW_PIN _LATC13
#define E_PIN _LATC15
 
void delay_ms(unsigned int n);
void send_nibble(unsigned char nibble);
void send_command_byte(unsigned char byte);
void send_data_byte(unsigned char byte);
void setup();

int get_distance();
int n;

int main()
{
	double d,cm;
	setup();
	
	TRISC = 0; // RC13-15 as digital outputs
    TRISB = 0xFFF0; // RB0-3 as digital outputs
    _PCFG0 = 1; // AN0 is digital
    _PCFG1 = 1; // AN1 is digital
    _PCFG2 = 1; // AN2 is digital
    _PCFG3 = 1; // AN3 is digital
 
    // Let's just write to the LCD and never read!
    // We'll wait 2ms after every command since we can't
    // check the busy flag.
    RW_PIN = 0;
    RS_PIN = 0;
    E_PIN = 1;
     
    // Initialisation
    delay_ms(16); // must be more than 15ms
    send_nibble(0b0011);
    delay_ms(5); // must be more than 4.1ms
    send_nibble(0b0011);
    delay_ms(1); // must be more than 100us
    send_nibble(0b0011);
    delay_ms(5); // must be more than 4.1ms
    send_nibble(0b0010); // select 4-bit mode
     
    // Display settings
    send_command_byte(0b00101000); // N=0 : 2 lines (half lines!), F=0 : 5x7 font
    send_command_byte(0b00001000); // Display: display off, cursor off, blink off
    send_command_byte(0b00000001); // Clear display
    send_command_byte(0b00000110); // Set entry mode: ID=1, S=0
    send_command_byte(0b00001111); // Display: display on, cursor on, blink on
     
    // Define two 8 character strings
	char line1[50]; // Text buffer - 16 characters for the screen, plus lots to spare
	char line2[50]; // Text buffer - 16 characters for the screen, plus lots to spare
    
    // Write the two strings to lines 1 and 2
	sprintf(line1, "Distance Meter  "); // display this text on start-up
	sprintf(line2, "By Aron Horan   "); // second line of text
	
	
    int n;
    send_command_byte(0x02); // Go to start of line 1
    for (n=0 ; n<=15 ; ++n) send_data_byte(line1[n]);
    send_command_byte(0xC0); // Go to start of line 2
    for (n=0 ; n<=15 ; ++n) send_data_byte(line2[n]);
	
	while(1)
	{
		d = get_distance(); //
		cm = (d / 27.0);	//
		sprintf(line2, "Distance:%.2fcm", cm);	// send string to LCD
		send_command_byte(0xC0); // Go to start of line 2
		for (n=0 ; n<=15 ; ++n) send_data_byte(line2[n]);
		printf("Distance:%.2fcmn", cm);
		__delay32(15000000); // delay 0.5seconds
	}
		
	return 0;
}
 
// Delay by specified number of milliseconds
void delay_ms(unsigned int n)
{
    while(n--) __delay32(30000);
}
 
void send_nibble(unsigned char nibble)
{
    // Note: data is latched on falling edge of pin E
    LATB = nibble;
    delay_ms(1);
    E_PIN = 0;
    delay_ms(1);
    E_PIN = 1;
    delay_ms(2); // Enough time even for slowest command
}
 
// Send a command byte (i.e. with pin RS low)
void send_command_byte(unsigned char byte)
{
    RS_PIN = 0;
    send_nibble(byte >> 4);
    send_nibble(byte & 0xF);
}
 
// Send a data byte (i.e. with pin RS high)
void send_data_byte(unsigned char byte)
{
    RS_PIN = 1;
    send_nibble(byte >> 4);
    send_nibble(byte & 0xF);
}

void setup()
{
	// Configure RD2 as output
	TRISD = 0b1011;
	
	// Configure Timer 2
    T2CONbits.TCKPS = 0b10; // Timer 2 prescaler 1:64
    PR2 = 9375;             // Timer 2 period (20ms)
    T2CONbits.TON = 1;      // Enable Timer 2

	// Configure UART
    U1BRG = 48;            // 38400 baud @ 30 MIPS
    U1MODEbits.UARTEN = 1; // Enable UART	
}

// send pulse to sensor and measure length of return pulse 
int get_distance()
{
	_LATD2=1;			// set rd2 high
	__delay32(3000); 	// wait 100 uS
	_LATD2=0;			// then set back low
	while (_RD0==0);	// wait to receive pulse from sensor
	TMR2=0;				// reset TMR2
	while (_RD0==1);	// time TMR2
	return TMR2;		// return value of TMR2
}

As shown in my code I simply needed to divide the output by 27 to convert into centimetres as the sensor was very linear within the ranges I was using it for.

Here is a video of it working (Not the best video but will make a better one soon)
Notice the LED 100us pulse on pin 22 (RD2) that goes to the trigger on the sensor.

Advertisements

3 thoughts on “Ultra Sonic Distance Meter

  1. Can’t see the video – is it there yet? Maybe it’s something to do with my browser.

  2. Another great project… You’ve really covered a lot of ground over the last couple of months!

  3. Pingback: Ultra Sonic Distance Meter | Ragnarok Connection

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s