Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of IEEE_14_Freescale by
hcsr04.h@33:03b0b66038e1, 2014-03-23 (annotated)
- Committer:
- sswatek
- Date:
- Sun Mar 23 02:23:29 2014 +0000
- Revision:
- 33:03b0b66038e1
- Parent:
- 31:4ef53fbd6759
able to move along the row of waves and find the gap
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| soonerbot | 14:a30aa3b29a2e | 1 | // Primary Author: David Glover |
| soonerbot | 14:a30aa3b29a2e | 2 | // March, 2012 |
| soonerbot | 14:a30aa3b29a2e | 3 | // ECE 510 Embedded Systems, Roy Kravitz |
| soonerbot | 14:a30aa3b29a2e | 4 | // |
| soonerbot | 14:a30aa3b29a2e | 5 | // HCSR04 ultrasonic sensor class using interrupts and allowing multiple instances. |
| soonerbot | 15:b10859606504 | 6 | // You can use the same trigger pin for multiple instances; the echo is received and |
| soonerbot | 15:b10859606504 | 7 | // measurement calculated based on the echo input alone. (when the echo signal goes high, |
| soonerbot | 15:b10859606504 | 8 | // the timer is started. When the echo signal goes low, the timer value in microseconds |
| soonerbot | 15:b10859606504 | 9 | // is saved as the length, and the timer is stopped and reset) Length calculation is done |
| soonerbot | 15:b10859606504 | 10 | // when the length is requested (either inches or centimeters). |
| soonerbot | 14:a30aa3b29a2e | 11 | |
| soonerbot | 14:a30aa3b29a2e | 12 | #ifndef MBED_HCSR04_H |
| soonerbot | 14:a30aa3b29a2e | 13 | #define MBED_HCSR04_H |
| soonerbot | 14:a30aa3b29a2e | 14 | |
| soonerbot | 14:a30aa3b29a2e | 15 | //required to use mbed functions |
| soonerbot | 14:a30aa3b29a2e | 16 | #include "mbed.h" |
| soonerbot | 14:a30aa3b29a2e | 17 | |
| soonerbot | 14:a30aa3b29a2e | 18 | #define TRIGGER_DELAY 12 // length of trigger signal expected by HCSR04 sensor |
| sswatek | 33:03b0b66038e1 | 19 | #define INCHES_DIVISOR 139 // |
| soonerbot | 14:a30aa3b29a2e | 20 | #define CM_DIVISOR 58 |
| soonerbot | 14:a30aa3b29a2e | 21 | |
| soonerbot | 14:a30aa3b29a2e | 22 | class hcsr04 { |
| soonerbot | 14:a30aa3b29a2e | 23 | |
| soonerbot | 14:a30aa3b29a2e | 24 | private: |
| soonerbot | 15:b10859606504 | 25 | InterruptIn *_echo_int; // pin to receive echo signal; input |
| soonerbot | 15:b10859606504 | 26 | DigitalOut trigger_out; // pin to send the trigger signal; output |
| soonerbot | 14:a30aa3b29a2e | 27 | Timer timer; // timer to track length of pulse |
| sswatek | 31:4ef53fbd6759 | 28 | volatile float value; // to store the last pulse length |
| soonerbot | 14:a30aa3b29a2e | 29 | |
| soonerbot | 14:a30aa3b29a2e | 30 | public: |
| soonerbot | 14:a30aa3b29a2e | 31 | bool measuring; // true while the echo signal is high (measurement in progress) |
| soonerbot | 14:a30aa3b29a2e | 32 | hcsr04(PinName trigger, PinName echo) : trigger_out(trigger) { // _pass the names to the pin configuration |
| soonerbot | 14:a30aa3b29a2e | 33 | //trigger_out = new DigitalOut( trigger ); |
| soonerbot | 15:b10859606504 | 34 | _echo_int = new InterruptIn( echo ); // interrupts |
| soonerbot | 15:b10859606504 | 35 | _echo_int->rise(this, &hcsr04::timer_start); // when trigger is sent |
| soonerbot | 15:b10859606504 | 36 | _echo_int->fall(this, &hcsr04::calc_measurement); // when echo is received |
| soonerbot | 14:a30aa3b29a2e | 37 | measuring = false; |
| soonerbot | 14:a30aa3b29a2e | 38 | } |
| soonerbot | 14:a30aa3b29a2e | 39 | |
| soonerbot | 14:a30aa3b29a2e | 40 | void calc_measurement() { |
| soonerbot | 14:a30aa3b29a2e | 41 | value = timer.read_us(); |
| soonerbot | 14:a30aa3b29a2e | 42 | //value = timer.read_us() - timestart; |
| soonerbot | 14:a30aa3b29a2e | 43 | timer.stop(); |
| soonerbot | 14:a30aa3b29a2e | 44 | timer.reset(); |
| soonerbot | 14:a30aa3b29a2e | 45 | measuring = false; |
| soonerbot | 14:a30aa3b29a2e | 46 | } |
| soonerbot | 14:a30aa3b29a2e | 47 | |
| soonerbot | 14:a30aa3b29a2e | 48 | void timer_start() { |
| sswatek | 31:4ef53fbd6759 | 49 | timer.reset(); |
| sswatek | 31:4ef53fbd6759 | 50 | timer.start(); |
| sswatek | 31:4ef53fbd6759 | 51 | //measuring = true; |
| soonerbot | 14:a30aa3b29a2e | 52 | } |
| soonerbot | 14:a30aa3b29a2e | 53 | |
| soonerbot | 14:a30aa3b29a2e | 54 | void trigger(void) { |
| soonerbot | 14:a30aa3b29a2e | 55 | trigger_out.write(1); // start trigger signal |
| soonerbot | 14:a30aa3b29a2e | 56 | wait_us(TRIGGER_DELAY); |
| soonerbot | 14:a30aa3b29a2e | 57 | trigger_out.write(0); // end trigger signal |
| sswatek | 31:4ef53fbd6759 | 58 | measuring = true; |
| sswatek | 31:4ef53fbd6759 | 59 | timer.reset(); |
| sswatek | 31:4ef53fbd6759 | 60 | timer.start(); |
| soonerbot | 14:a30aa3b29a2e | 61 | } |
| soonerbot | 14:a30aa3b29a2e | 62 | |
| soonerbot | 14:a30aa3b29a2e | 63 | float inches() { // return distance in inches. |
| soonerbot | 14:a30aa3b29a2e | 64 | return value / INCHES_DIVISOR; |
| soonerbot | 14:a30aa3b29a2e | 65 | } |
| soonerbot | 14:a30aa3b29a2e | 66 | |
| soonerbot | 14:a30aa3b29a2e | 67 | float cm() { // return distance in centimeters. |
| soonerbot | 14:a30aa3b29a2e | 68 | return value / CM_DIVISOR; |
| soonerbot | 14:a30aa3b29a2e | 69 | } |
| sswatek | 31:4ef53fbd6759 | 70 | |
| soonerbot | 14:a30aa3b29a2e | 71 | |
| sswatek | 31:4ef53fbd6759 | 72 | //finds a stable distance value by taking count samples and putting them into buckets |
| sswatek | 31:4ef53fbd6759 | 73 | // of +-%10 that are moving averages |
| sswatek | 31:4ef53fbd6759 | 74 | // returns the distance in inches of a measurement with at least thresh results |
| sswatek | 31:4ef53fbd6759 | 75 | // returns -1 if no consensus was found and returns -2 if none of the samples were less than 19 inches away |
| sswatek | 31:4ef53fbd6759 | 76 | // which would indicate a "far" read |
| sswatek | 31:4ef53fbd6759 | 77 | float getStablePollAdv(int count, int thresh){ |
| sswatek | 31:4ef53fbd6759 | 78 | float distBuckets[7] = {0,0,0,0,0,0,0}; |
| sswatek | 31:4ef53fbd6759 | 79 | int bucketCount[7] = {0,0,0,0,0,0,0}; |
| sswatek | 31:4ef53fbd6759 | 80 | for(int i=0;i<count;i++){ |
| sswatek | 31:4ef53fbd6759 | 81 | trigger(); |
| sswatek | 31:4ef53fbd6759 | 82 | while(measuring && timer.read_ms()<200); |
| sswatek | 31:4ef53fbd6759 | 83 | if(!measuring){ |
| sswatek | 31:4ef53fbd6759 | 84 | //store value |
| sswatek | 31:4ef53fbd6759 | 85 | for(int j=0;j<7;j++){ |
| sswatek | 31:4ef53fbd6759 | 86 | if(bucketCount[j]==0){ |
| sswatek | 31:4ef53fbd6759 | 87 | //bucket empty, add to bucket |
| sswatek | 31:4ef53fbd6759 | 88 | distBuckets[j]=value; |
| sswatek | 31:4ef53fbd6759 | 89 | bucketCount[j]++; |
| sswatek | 31:4ef53fbd6759 | 90 | break; |
| sswatek | 31:4ef53fbd6759 | 91 | } else if(value > distBuckets[j]*0.9 && value < distBuckets[j]*1.1){ |
| sswatek | 31:4ef53fbd6759 | 92 | //within range of center bucket, add |
| sswatek | 31:4ef53fbd6759 | 93 | distBuckets[j] = (distBuckets[j]*bucketCount[j]+value)/(bucketCount[j]+1); |
| sswatek | 31:4ef53fbd6759 | 94 | bucketCount[j]++; |
| sswatek | 31:4ef53fbd6759 | 95 | break; |
| sswatek | 31:4ef53fbd6759 | 96 | } |
| sswatek | 31:4ef53fbd6759 | 97 | } |
| sswatek | 31:4ef53fbd6759 | 98 | } |
| sswatek | 31:4ef53fbd6759 | 99 | } |
| sswatek | 31:4ef53fbd6759 | 100 | int maxBucket=0; |
| sswatek | 31:4ef53fbd6759 | 101 | int numBelowCutoff=0; // this is used to track if any values are below a cutoff |
| sswatek | 31:4ef53fbd6759 | 102 | const float cutoff=19.0 * INCHES_DIVISOR; |
| sswatek | 31:4ef53fbd6759 | 103 | if(distBuckets[0]<cutoff) |
| sswatek | 31:4ef53fbd6759 | 104 | numBelowCutoff += bucketCount[0]; |
| sswatek | 31:4ef53fbd6759 | 105 | //DBGPRINT("Bucket #0 has %d at %f\r\n",bucketCount[0],distBuckets[0] / INCHES_DIVISOR); |
| sswatek | 31:4ef53fbd6759 | 106 | for(int i=1;i<7;i++){ |
| sswatek | 31:4ef53fbd6759 | 107 | // cycling through the values to find the bucket with the most members |
| sswatek | 31:4ef53fbd6759 | 108 | if(distBuckets[i]<cutoff) |
| sswatek | 31:4ef53fbd6759 | 109 | numBelowCutoff += bucketCount[i]; |
| sswatek | 31:4ef53fbd6759 | 110 | //DBGPRINT("Bucket #%d has %d at %f\r\n",i,bucketCount[i],distBuckets[i] / INCHES_DIVISOR); |
| sswatek | 31:4ef53fbd6759 | 111 | if(bucketCount[maxBucket]<bucketCount[i]) |
| sswatek | 31:4ef53fbd6759 | 112 | maxBucket=i; |
| sswatek | 31:4ef53fbd6759 | 113 | } |
| sswatek | 31:4ef53fbd6759 | 114 | if(bucketCount[maxBucket]>=thresh){ |
| sswatek | 31:4ef53fbd6759 | 115 | return distBuckets[maxBucket] / INCHES_DIVISOR; |
| sswatek | 31:4ef53fbd6759 | 116 | } else if(numBelowCutoff==0){ |
| sswatek | 31:4ef53fbd6759 | 117 | return -2; |
| sswatek | 31:4ef53fbd6759 | 118 | }else{ |
| sswatek | 31:4ef53fbd6759 | 119 | return -1; |
| sswatek | 31:4ef53fbd6759 | 120 | } |
| sswatek | 31:4ef53fbd6759 | 121 | } |
| sswatek | 31:4ef53fbd6759 | 122 | |
| sswatek | 31:4ef53fbd6759 | 123 | // (15,8) seems to give good results, so this convienence function can be used for these defaults |
| sswatek | 31:4ef53fbd6759 | 124 | float getStablePoll(void){ |
| sswatek | 31:4ef53fbd6759 | 125 | return getStablePollAdv(15,8); |
| sswatek | 31:4ef53fbd6759 | 126 | } |
| sswatek | 31:4ef53fbd6759 | 127 | |
| soonerbot | 15:b10859606504 | 128 | /* void hscr04_main(void) { // Rohan's code |
| soonerbot | 15:b10859606504 | 129 | //trigger(); |
| soonerbot | 15:b10859606504 | 130 | // delay |
| soonerbot | 14:a30aa3b29a2e | 131 | while(measuring == false); |
| soonerbot | 14:a30aa3b29a2e | 132 | // interrupts call timer_start() and calc_measurement() |
| soonerbot | 14:a30aa3b29a2e | 133 | } |
| soonerbot | 14:a30aa3b29a2e | 134 | */ |
| soonerbot | 14:a30aa3b29a2e | 135 | |
| soonerbot | 14:a30aa3b29a2e | 136 | }; |
| soonerbot | 14:a30aa3b29a2e | 137 | |
| soonerbot | 14:a30aa3b29a2e | 138 | #endif |
