William Toth
Navigation
Home
Tutorials
Links

Portfolio
Programming
FIRST Robotics
Hockey
3d Art and Designs
Company of Heroes Mod
Hardware Creations
Music
Other Projects

Contact
Email
Instant Messaging
Phone

Ultrasonic Sensor Code

Note: This code works with up to 2 ultrasonic sensors in either port 1 or 2. which can be configured by commenting out or removing comments. Thank you Kevin for the inspiration.



Ultrasonic.h

/*
  Program for Parallax PING))) ultrasonic sensor
  www.parallax.com
  Author: William Toth
  Date: 01/22/08
  Description: Sets up all things needed to measure the pulses
  created by the sensor. This can use up to 2 sensors
*/


#ifndef __ULTRASONIC_HEADER__

#define __ULTRASONIC_HEADER__


//Choose which digital pin will be the output

//you may only need one pin for this unless the sensors

//are in conflicting direction. Make sure it is

//set as an OUTPUT in user_routines.c In this

//example I am going to use two so I can control

//each indevidually

#define ULTRASONIC_OUTPUT_PORT1 rc_dig_out15;

#define ULTRASONIC_OUTPUT_PORT2 rc_dig_out14;


//We only need one input port if we have 2 output ports so

//that frees up one interrupt port, and 1 & 2 are

//the best/easiest to use. Comment out the one you dont

//want to use

#define ULTRASONIC_INTERRUPT_PORT1 rc_dig_in01;

//#define ULTRASONIC_INTERRUPT_PORT2 rc_dig_in02;


//Do not change these are used for the arguments

//in the functions for which sensor you want

#define ULTRASONIC_SENSOR1 1;

#define ULTRASONIC_SENSOR2 2;



//Variable used for the interrupt routine to

//Tell which sensor is being used

extern unsigned char UltrasonicNumber;


//Copy of the time for each of the 2 sensors

extern volatile unsigned int Ultrasonic_1_Time;
extern volatile unsigned int Ultrasonic_2_Time;

//Call in User_Initilization in User_Routines.c

void Initilize_Ultrasonic(void);

//Use to test your sensor

unsigned int Ping_Test(unsigned char Sensor_Number);

//Use this before you get the distance

void Ping(unsigned char Sensor_Number);

//Get the current distance on a certain sensor

unsigned int Get_Distance(unsigned char Sensor_Number);

//Disable Ultrasonic sensor on a certain port

void Disable_Ultrasonic(unsigned char Sensor_Number);

//Enable Ultrasonic sensor on a certain port;

void Enable_Ultrasonic(unsigned char Sensor_Number);

//Interrupt routine. replace "INTCON3bits.INT2IF = 0;"

//in user_routines_fast.c with "Ultrasonic_Interrupt_Routine()"

//if you are using interrupt port 1

//or "INTCON3bits.INT3IF = 0;" for port 2

void Ultrasonic_Interrupt_Routine(void);

#endif



#ifndef ULTRASONIC_INTERRUPT_PORT1

#ifndef ULTRASONIC_INTERRUPT_PORT2

#error You must select one interrupt port to use!

#endif

#endif





Ultrasonic.c

/*
  Program for Parallax PING))) ultrasonic sensor
  www.parallax.com
  Author: William Toth
  Date: 01/22/08
  Description: Sets up all things needed to measure the pulses
  created by the sensor. This can use 2 sensors. Each sensor gets
  wired to 1 interrupt port (either 1 or 2) and one regular port that
  you define below
*/

#include "ifi_default.h"

#include "Ultrasonic.h"

#include "ifi_aliases.h"


//Variable used for the interrupt routine to

//Tell which sensor is being used

unsigned char UltrasonicNumber;

//Copy of the time for each of the 2 sensors

volatile unsigned int Ultrasonic_1_Time;
volatile unsigned int Ultrasonic_2_Time;

//Call in User_Initilization in User_Routines.c

void Initilize_Ultrasonic(void)
{
      //Set what you want for this timer. In my case

      //I am using a prescaler of 8.

      T3CON = 0b00110000;


      //check to see which port you chose

      #ifdef ULTRASONIC_INTERRUPT_PORT1


      // make sure interrupt 1 is configured as an input

      //it is in the default code "digital_io_01" is the

      //same as   "TRISBbits.TRISB2"

      TRISBbits.TRISB2 = 1;

      // interrupt 1 is low priority

      INTCON3bits.INT2IP = 0;

      // trigger on rising edge

      INTCON2bits.INTEDG2 = 1;

      // make sure the interrupt flag is reset before enabling

      INTCON3bits.INT2IF = 0;

      //keep disabled it for now

      INTCON3bits.INT2IE = 0;
      #endif



      #ifdef ULTRASONIC_INTERRUPT_PORT2

      // make sure interrupt 2 is configured as an input

      //it is in the default code

      TRISBbits.TRISB3 = 1;

      // interrupt 2 is low priority

     
/*Note: If you get an error on this line saying
      "Unknownn tag _INT3IP_ or something like that
      go into the file p18f8722.h in C:\mcc18\h and change the
    line that says "INT3P" to "INT3IP"   */

      INTCON2bits.INT3IP = 0;

      // trigger on rising edge

      INTCON2bits.INTEDG3 = 1;

      // make sure the interrupt flag is reset before enabling

      INTCON3bits.INT3IF = 0;

      //keep disabled it for now

      INTCON3bits.INT3IE = 0;      
      #endif

     
}
     

//Use to test your sensor

unsigned int Ping_Test(unsigned char Sensor_Number);

void Ping(unsigned char Sensor_Number)
{
      unsigned short x; //for counter


      //Set it to get input on rising edge

      INTCON2bits.INTEDG2 = 1;

      //Set which sensor we are using      

      UltrasonicNumber = Sensor_Number;
     
      #ifdef ULTRASONIC_INTERRUPT_PORT1


      //Enable the interrupt on port 1

      INTCON3bits.INT2IE = 1;

      #endif      

     

      #ifdef ULTRASONIC_INTERRUPT_PORT2


      //Enable the interrupt

      INTCON3bits.INT3IE = 1;

      #endif


     

      //Turn the timer on

      T3CONbits.TMR3ON = 1;

     
      //Set it to output to start the pulse

      if(Sensor_Number==1)
      {
              //ULTRASONIC_OUTPUT_PORT1 = 1;

              rc_dig_out15 = 1;
      }
      else if(Sensor_Number==2)
      {
              //ULTRASONIC_OUTPUT_PORT2 = 1;

              rc_dig_out14 = 1;
      }


      //wait for 2-5 us (approx)

      for(;x<=10;x++);

      //stop the pulse

      if(Sensor_Number==1)
      {
              //ULTRASONIC_OUTPUT_PORT1=0;

              rc_dig_out15 = 0;
      }
      else if(Sensor_Number==2)
      {
              //ULTRASONIC_OUTPUT_PORT2=0;

              rc_dig_out14 = 0;
      }      


}

//Get the current distance on a certain sensor

unsigned int Get_Distance(unsigned char Sensor_Number)
{
              //So that everytime the code runs this function we get the same value we

              //wont edit the timer value

              unsigned int ReturnValue;


              //Disable Interrupts while accessing the values.

              #ifdef ULTRASONIC_INTERRUPT_PORT1


              //disable the interrupt on port 1

              INTCON3bits.INT2IE = 0;
     
              #endif      

             

              #ifdef ULTRASONIC_INTERRUPT_PORT2


              //disable the interrupt

              INTCON3bits.INT3IE = 0;

              #endif





              //The speed of sound is 340.29 m/s or

              //13,560 feet/second, but the metric sytem is much much

              //easier to work with So that is 340,290 mm/s

              //1 second = 1,000,000 us (microseconds)

              //so .34029 mm/us

              //For the timer the equation is as follows:

              // (prescale factor)*(Timer value)=time elapsed in us

              //   prescale we use is 8

              if(Sensor_Number == 1)                              
              {
                      //Devide by 2 because the reading we get is timer there and time back

                      ReturnValue = Ultrasonic_1_Time / 2;

                     
/*****Enable the interrupt again****/

                              #ifdef ULTRASONIC_INTERRUPT_PORT1


                              //Enable the interrupt on port 1

                              INTCON3bits.INT2IE = 1;

                              #endif      

     

                              #ifdef ULTRASONIC_INTERRUPT_PORT2


                              //Enable the interrupt

                              INTCON3bits.INT3IE = 1;

                              #endif


                      //Now plugin our equation ReturnValue = TimerValue

                      ReturnValue *= 8;
                     
                      // the *11 and >> 6 is the same as ReturnValue * .34029

                      //except that it is faster then using a float

                      //return (ReturnValue*11)>>6; //This is in milimeters

                      return ReturnValue * .34029;
              }

              else if(Sensor_Number == 2)
              {
                      //Devide by 2 because the reading we get is timer there and time back

                      ReturnValue = Ultrasonic_2_Time / 2;


                     
/*****Enable the interrupt again****/

                              #ifdef ULTRASONIC_INTERRUPT_PORT1


                              //Enable the interrupt on port 1

                              INTCON3bits.INT2IE = 1;

                              #endif      

     

                              #ifdef ULTRASONIC_INTERRUPT_PORT2


                              //Enable the interrupt

                              INTCON3bits.INT3IE = 1;

                              #endif



                      //Now plugin our equation ReturnValue = TimerValue

                      ReturnValue *= 8;
                     
                      // the *11 and >> 6 is the same as ReturnValue * .34029

                      return ((ReturnValue*11)>>6); //This is in milimeters

              }

}
//Disable Ultrasonic sensor on a certain port

void Disable_Ultrasonic(unsigned char Sensor_Number);

//Enable Ultrasonic sensor on a certain port

//only use after a Disable function has been called

void Enable_Ultrasonic(unsigned char Sensor_Number);

//Interrupt routine. replace "INTCON3bits.INT2IF = 0;"

//in user_routines_fast.c with "Ultrasonic_Interrupt_Routine()"

//if you are using interrupt port 1

//or "INTCON3bits.INT3IF = 0;" for port 2

void Ultrasonic_Interrupt_Routine(void)
{
      //If the interrupt for rising edge hasnt happened

      if(INTCON2bits.INTEDG2)
      {
              //reset the timer;

              TMR3H = 0x00;
              TMR3L = 0x00;
     
              #ifdef ULTRASONIC_INTERRUPT_PORT1

              // trigger the next one on falling edge

              INTCON2bits.INTEDG2 = 0;
              #endif


              #ifdef ULTRASONIC_INTERRUPT_PORT2

              // trigger the next one on falling edge

              INTCON2bits.INTEDG3 = 0;
              #endif


      }
      else
      {
              //turn off the timer

              T3CONbits.TMR3ON = 0;

              #ifdef ULTRASONIC_INTERRUPT_PORT1

              // trigger the next one on rising edge

              INTCON2bits.INTEDG2 = 1;
              #endif


              #ifdef ULTRASONIC_INTERRUPT_PORT2

              // trigger the next one on rising edge

              INTCON2bits.INTEDG3 = 1;
              #endif

             
             
/*
              //Store the time

              Ultrasonic_1_Time = (unsigned int)TMR3H<<8;
              Ultrasonic_1_Time |= (unsigned int)TMR3L;
              */

             
              if(UltrasonicNumber==1)
              {
                      //Store the time

                      Ultrasonic_1_Time = (unsigned int)TMR3H<<8;
                      Ultrasonic_1_Time |= TMR3L;
                      //UltrasonicNumber |= 0x80;

              }
             
              else if(UltrasonicNumber==2)
              {
                      //Store the time

                      Ultrasonic_2_Time = (unsigned int)TMR3H<<8;
                      Ultrasonic_2_Time |= TMR3L;
                      //UltrasonicNumber &= 0x7F;

              }
      }


}





Click Here for the non-functioning code meant for ports 3-6. I could not figure out why I couldn't get it to work.