├── cleanDirs.sh ├── README ├── keywords.txt ├── examples ├── UltrasonicDemo │ └── UltrasonicDemo.pde └── UltrasonicStdDev │ └── UltrasonicStdDev.pde ├── Makefile ├── Ultrasonic.h └── Ultrasonic.cpp /cleanDirs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Clean the dir tree of backup and compiled files before doing a checkin. 4 | # 5 | 6 | REGEX="(^.*.pyc$)|(^.*~$)|(.*#$)|(.*\.log(.*)?)" 7 | CMD="find . -regextype posix-egrep -regex $REGEX" 8 | 9 | if [ "$1" == "clean" ]; then 10 | $CMD -exec rm {} \; 11 | else 12 | $CMD 13 | fi 14 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This library was created to work with the HC-SR04 Ultrasonic sensor. 2 | 3 | It features timing, metric conversion (centimeter and inch) and standard 4 | deviation methods. Some ideas were gleaned from a library created by ITead 5 | studio at iteadstudio.com. 6 | 7 | Look at the code and examples to understand how the library works. 8 | 9 | The standerd deviation code can be removed from the compilation resulting in 10 | a significant savings of resources. To do this comment the 11 | 12 | #define COMPILE_STD_DEV 13 | 14 | definition in the header file. 15 | 16 | 17 | mailto://carl.nobile@gmail.com 18 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map Ultrasonic 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | Ultrasonic KEYWORD1 9 | 10 | ####################################### 11 | # Methods and Functions (KEYWORD2) 12 | ####################################### 13 | timing KEYWORD2 14 | convent KEYWORD2 15 | sampleCreate KEYWORD2 16 | sampleClear KEYWORD2 17 | unbiasedStdDev KEYWORD2 18 | 19 | ####################################### 20 | # Constants (LITERAL1) 21 | ####################################### 22 | -------------------------------------------------------------------------------- /examples/UltrasonicDemo/UltrasonicDemo.pde: -------------------------------------------------------------------------------- 1 | /* 2 | * HCSR04Ultrasonic/examples/UltrasonicDemo/UltrasonicDemo.pde 3 | * 4 | * SVN Keywords 5 | * ---------------------------------- 6 | * $Author: cnobile $ 7 | * $Date: 2011-09-17 02:43:12 -0400 (Sat, 17 Sep 2011) $ 8 | * $Revision: 29 $ 9 | * ---------------------------------- 10 | */ 11 | 12 | #include 13 | 14 | #define TRIGGER_PIN 12 15 | #define ECHO_PIN 13 16 | 17 | Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | } 23 | 24 | void loop() 25 | { 26 | float cmMsec, inMsec; 27 | long microsec = ultrasonic.timing(); 28 | 29 | cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); 30 | inMsec = ultrasonic.convert(microsec, Ultrasonic::IN); 31 | Serial.print("MS: "); 32 | Serial.print(microsec); 33 | Serial.print(", CM: "); 34 | Serial.print(cmMsec); 35 | Serial.print(", IN: "); 36 | Serial.println(inMsec); 37 | delay(1000); 38 | } 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the HCSR04Ultrasonic library. 3 | # 4 | # $Author: cnobile $ 5 | # $Date: 2011-12-07 21:53:24 -0500 (Wed, 07 Dec 2011) $ 6 | # $Revision: 39 $ 7 | # 8 | 9 | # Local directory locations. 10 | PACKAGE_PREFIX = $(shell pwd) 11 | PACKAGE_DIR = $(shell echo $${PWD\#\#*/}) 12 | TODAY = $(shell date +"%Y-%m-%d") 13 | 14 | # Current version 15 | MAJORVERSION = 1 16 | MINORVERSION = 1 17 | PATCHLEVEL = 2 18 | VERSION = ${MAJORVERSION}.${MINORVERSION}.${PATCHLEVEL} 19 | 20 | DISTNAME = ${PACKAGE_DIR}-$(VERSION) 21 | SVN_PATH = /exports/nas-storage/cnobile/repos/svnroot/arduino-svn/HCSR04Ultrasonic 22 | 23 | #-------------------------------------------------------------- 24 | all : clobber 25 | (cd ..; tar -czvf $(DISTNAME).tar.gz --exclude .svn $(PACKAGE_DIR)) 26 | (cd ..; zip -r $(DISTNAME).zip $(PACKAGE_DIR)/* --exclude \*/.svn\*) 27 | 28 | svn-tag : 29 | svn copy svn+ssh://foundation${SVN_PATH}/trunk \ 30 | svn+ssh://foundation${SVN_PATH}/tags/tag-${VERSION}-${TODAY} \ 31 | -m "Tag--release $(VERSION)." 32 | 33 | #-------------------------------------------------------------- 34 | clean : 35 | $(shell $(PACKAGE_PREFIX)/cleanDirs.sh clean) 36 | 37 | clobber : clean 38 | @(cd ..; rm -rf $(DISTNAME).tar.gz $(DISTNAME).zip) 39 | -------------------------------------------------------------------------------- /Ultrasonic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Ultrasonic.h - Library for HC-SR04 Ultrasonic Sensing Module. 3 | * 4 | * With ideas from: 5 | * Created by ITead studio. Alex, Apr 20, 2010. 6 | * iteadstudio.com 7 | * 8 | * SVN Keywords 9 | * ---------------------------------- 10 | * $Author: cnobile $ 11 | * $Date: 2011-12-07 21:49:14 -0500 (Wed, 07 Dec 2011) $ 12 | * $Revision: 38 $ 13 | * ---------------------------------- 14 | * 15 | * Thank you to Rowan Simms for pointing out the change in header name with 16 | * Arduino version 1.0 and up. 17 | * 18 | */ 19 | 20 | #ifndef ULTRASONIC_H 21 | #define ULTRASONIC_H 22 | 23 | #include 24 | 25 | #if defined(ARDUINO) && ARDUINO >= 100 26 | #include 27 | #else 28 | #include 29 | #endif 30 | 31 | // Undefine COMPILE_STD_DEV if you don't want Standard Deviation. 32 | #define COMPILE_STD_DEV 33 | 34 | 35 | typedef struct bufferCtl 36 | { 37 | float *pBegin; 38 | float *pIndex; 39 | size_t length; 40 | bool filled; 41 | } BufCtl; 42 | 43 | class Ultrasonic 44 | { 45 | public: 46 | Ultrasonic(int tp, int ep); 47 | long timing(); 48 | float convert(long microsec, int metric); 49 | void setDivisor(float value, int metric); 50 | static const int IN = 0; 51 | static const int CM = 1; 52 | 53 | #ifdef COMPILE_STD_DEV 54 | bool sampleCreate(size_t size, ...); 55 | void sampleClear(); 56 | float unbiasedStdDev(float value, size_t bufNum); 57 | #endif // COMPILE_STD_DEV 58 | 59 | private: 60 | int _trigPin; 61 | int _echoPin; 62 | float _cmDivisor; 63 | float _inDivisor; 64 | 65 | #ifdef COMPILE_STD_DEV 66 | size_t _numBufs; 67 | BufCtl *_pBuffers; 68 | void _sampleUpdate(BufCtl *buf, float msec); 69 | void _freeBuffers(); 70 | #endif // COMPILE_STD_DEV 71 | }; 72 | 73 | #endif // ULTRASONIC_H 74 | -------------------------------------------------------------------------------- /examples/UltrasonicStdDev/UltrasonicStdDev.pde: -------------------------------------------------------------------------------- 1 | /* 2 | * HCSR04Ultrasonic/examples/UltrasonicStdDev/UltrasonicStdDev.pde 3 | * 4 | * SVN Keywords 5 | * ---------------------------------- 6 | * $Author: cnobile $ 7 | * $Date: 2011-09-17 02:43:12 -0400 (Sat, 17 Sep 2011) $ 8 | * $Revision: 29 $ 9 | * ---------------------------------- 10 | */ 11 | 12 | #include 13 | 14 | #define TRIGGER_PIN 12 15 | #define ECHO_PIN 13 16 | 17 | #define NUMBER_BUFFERS 3 18 | #define BUFFER_SIZE 3 19 | 20 | #define BUFFER_01 0 21 | #define BUFFER_02 1 22 | #define BUFFER_03 2 23 | 24 | Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); 25 | bool disableSD = false; 26 | 27 | // Only run 50 time so we can reburn the code easily. 28 | #define CYCLES 50 29 | size_t count = 0; 30 | 31 | 32 | void setup() 33 | { 34 | Serial.begin(9600); 35 | Serial.println("Starting Ultasonic Test using standard deviation ..."); 36 | 37 | /* 38 | * If NUMBER_BUFFERS is 2 then it must be followed by two size variables 39 | * one for each buffer to be created. The size variables do not need to be 40 | * the same value. 41 | * 42 | * Example: ultrasonic.sampleCreate(3, 20, 10, 3) is valid. 43 | * 44 | * Note: The minimum size for any buffer is 2. Using less than 2 will waist 45 | * resources and the buffer will be ignored. 46 | */ 47 | if(!ultrasonic.sampleCreate(NUMBER_BUFFERS, BUFFER_SIZE, BUFFER_SIZE, 48 | BUFFER_SIZE)) 49 | { 50 | disableSD = true; 51 | Serial.println("Could not allocate memory."); 52 | } 53 | } 54 | 55 | void loop() 56 | { 57 | float cmMsec, inMsec; 58 | float msStdDev, cmStdDev, inStdDev; 59 | long microsec = ultrasonic.timing(); 60 | 61 | cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); 62 | inMsec = ultrasonic.convert(microsec, Ultrasonic::IN); 63 | 64 | if(count < CYCLES) 65 | { 66 | if(disableSD) 67 | { 68 | Serial.print("CM: "); 69 | Serial.print(cmMsec); 70 | Serial.print(", IN: "); 71 | Serial.println(inMsec); 72 | } 73 | else 74 | { 75 | msStdDev = ultrasonic.unbiasedStdDev((float) microsec, BUFFER_01); 76 | cmStdDev = ultrasonic.unbiasedStdDev(cmMsec, BUFFER_02); 77 | inStdDev = ultrasonic.unbiasedStdDev(inMsec, BUFFER_03); 78 | Serial.print(count + 1); 79 | Serial.print(") MS: "); 80 | Serial.print(microsec); 81 | Serial.print(", SD: "); 82 | Serial.print(msStdDev); 83 | Serial.print(", CM: "); 84 | Serial.print(cmMsec); 85 | Serial.print(", SD: "); 86 | Serial.print(cmStdDev, 2); 87 | Serial.print(", IN: "); 88 | Serial.print(inMsec); 89 | Serial.print(", SD: "); 90 | Serial.println(inStdDev, 2); 91 | } 92 | 93 | count++; 94 | } 95 | 96 | delay(1000); 97 | } 98 | -------------------------------------------------------------------------------- /Ultrasonic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Ultrasonic.cpp - Library for HC-SR04 Ultrasonic Sensing Module. 3 | * 4 | * With ideas from: 5 | * Created by ITead studio. Apr 20, 2010. 6 | * iteadstudio.com 7 | * 8 | * SVN Keywords 9 | * ---------------------------------- 10 | * $Author: cnobile $ 11 | * $Date: 2011-10-08 21:07:42 -0400 (Sat, 08 Oct 2011) $ 12 | * $Revision: 35 $ 13 | * ---------------------------------- 14 | * 15 | * Centimeters Divisor 16 | * =========== ======= 17 | * 15.875 26.9029 18 | * 46.355 27.6233 19 | * 92.075 28.1949 20 | * 137.795 28.4717 21 | * 183.515 28.5584 22 | * 229.235 28.5936 23 | * 274.955 28.7194 24 | * 25 | * Inches Divisor 26 | * ====== ======= 27 | * 6.25 68.3333 28 | * 18.25 70.1633 29 | * 36.25 71.6152 30 | * 54.25 72.3182 31 | * 72.25 72.5384 32 | * 90.25 72.6277 33 | * 108.25 72.9473 34 | */ 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | Ultrasonic::Ultrasonic(int tp, int ep) 42 | { 43 | pinMode(tp, OUTPUT); 44 | pinMode(ep, INPUT); 45 | _trigPin = tp; 46 | _echoPin = ep; 47 | _cmDivisor = 27.6233; 48 | _inDivisor = 70.1633; 49 | } 50 | 51 | long Ultrasonic::timing() 52 | { 53 | digitalWrite(_trigPin, LOW); 54 | delayMicroseconds(2); 55 | digitalWrite(_trigPin, HIGH); 56 | delayMicroseconds(10); 57 | digitalWrite(_trigPin, LOW); 58 | return pulseIn(_echoPin, HIGH); 59 | } 60 | 61 | float Ultrasonic::convert(long microsec, int metric) 62 | { 63 | // microsec / 29 / 2; 64 | if(metric) return microsec / _cmDivisor / 2.0; // CM 65 | // microsec / 74 / 2; 66 | else return microsec / _inDivisor / 2.0; // IN 67 | } 68 | 69 | void Ultrasonic::setDivisor(float value, int metric) 70 | { 71 | if(metric) _cmDivisor = value; 72 | else _inDivisor = value; 73 | } 74 | 75 | #ifdef COMPILE_STD_DEV 76 | bool Ultrasonic::sampleCreate(size_t numBufs, ...) 77 | { 78 | bool result = false; 79 | va_list ap; 80 | _numBufs = numBufs; 81 | 82 | if((_pBuffers = (BufCtl *) calloc(numBufs, sizeof(BufCtl))) != NULL) 83 | { 84 | va_start(ap, numBufs); 85 | BufCtl *buf; 86 | size_t smpSize; 87 | 88 | for(size_t i = 0; i < _numBufs; i++) 89 | { 90 | buf = &_pBuffers[i]; 91 | smpSize = va_arg(ap, size_t); 92 | 93 | if((buf->pBegin = (float *) calloc(smpSize, sizeof(float))) != NULL) 94 | { 95 | buf->pIndex = buf->pBegin; 96 | buf->length = smpSize; 97 | buf->filled = false; 98 | result = true; 99 | } 100 | else 101 | { 102 | result = false; 103 | break; 104 | } 105 | } 106 | 107 | va_end(ap); 108 | } 109 | 110 | if(!result) _freeBuffers(); 111 | return result; 112 | } 113 | 114 | void Ultrasonic::sampleClear() 115 | { 116 | if(_pBuffers) 117 | { 118 | BufCtl *buf; 119 | 120 | for(size_t i = 0; i < _numBufs; i++) 121 | { 122 | buf = &_pBuffers[i]; 123 | memset(buf, '\0', sizeof(float) * buf->length); 124 | buf->pIndex = buf->pBegin; 125 | buf->filled = false; 126 | } 127 | } 128 | } 129 | 130 | float Ultrasonic::unbiasedStdDev(float value, size_t bufNum) 131 | { 132 | float result = 0.0; 133 | 134 | if(_pBuffers) 135 | { 136 | BufCtl *buf = &_pBuffers[bufNum]; 137 | 138 | if(buf->length > 1) 139 | { 140 | _sampleUpdate(buf, float(value)); 141 | 142 | if(buf->filled) 143 | { 144 | float sum = 0.0, mean, tmp; 145 | 146 | for(size_t i = 0; i < buf->length; i++) 147 | sum += buf->pBegin[i]; 148 | 149 | mean = sum / buf->length; 150 | sum = 0.0; 151 | 152 | for(size_t i = 0; i < buf->length; i++) 153 | { 154 | tmp = buf->pBegin[i] - mean; 155 | sum += (tmp * tmp); 156 | } 157 | 158 | result = sqrt(sum / (buf->length - 1)); 159 | //Serial.print(bufNum); 160 | //Serial.print(" : "); 161 | //Serial.println(result); 162 | } 163 | } 164 | } 165 | 166 | return result; 167 | } 168 | 169 | void Ultrasonic::_sampleUpdate(BufCtl *buf, float msec) 170 | { 171 | if(buf->pIndex >= (buf->pBegin + buf->length)) 172 | { 173 | buf->pIndex = buf->pBegin; 174 | buf->filled = true; 175 | } 176 | 177 | *(buf->pIndex++) = msec; 178 | } 179 | 180 | void Ultrasonic::_freeBuffers() 181 | { 182 | if(_pBuffers) 183 | { 184 | BufCtl *buf; 185 | 186 | for(size_t i = 0; i < _numBufs; i++) 187 | { 188 | buf = &_pBuffers[i]; 189 | free(buf->pBegin); 190 | } 191 | 192 | free(_pBuffers); 193 | } 194 | } 195 | #endif // COMPILE_STD_DEV 196 | --------------------------------------------------------------------------------