// // FILE: SRF05.cpp // AUTHOR: Rob Tillaart // VERSION: 0.3.0 // DATE: 2021-05-17 // PURPOSE: Arduino library for the SRF05 distance sensor (and compatibles) // URL: https://github.com/RobTillaart/SRF05 #include "SRF05.h" ///////////////////////////////////////////////////// // // CONSTRUCTORS // SRF05::SRF05(const uint8_t trigger, const uint8_t echo) { _trigger = trigger; _echo = echo; _mode = SRF05_MODE_SINGLE; if (echo == 0) { _echo = _trigger; } pinMode(_trigger, OUTPUT); digitalWrite(_trigger, LOW); } void SRF05::setSpeedOfSound(float speedOfSound) { _speedOfSound = speedOfSound; } float SRF05::getSpeedOfSound() { return _speedOfSound; } bool SRF05::setCorrectionFactor(float factor) { if (factor <= 0) return false; _correctionFactor = factor; return true; } float SRF05::getCorrectionFactor() { return _correctionFactor; } ////////////////////////////////////////////////// // // OPERATIONAL MODE // void SRF05::setModeSingle() { _mode = SRF05_MODE_SINGLE; _count = 1; } void SRF05::setModeAverage(uint8_t count) { _mode = SRF05_MODE_AVERAGE; if (_count == 0) _count = 1; _count = count; } void SRF05::setModeMedian(uint8_t count) { _mode = SRF05_MODE_MEDIAN; _count = count; if (_count < 3) _count = 3; if (_count > 15) _count = 15; } void SRF05::setModeRunningAverage(float alpha) { _mode = SRF05_MODE_RUN_AVERAGE; _count = 1; _alpha = alpha; } uint8_t SRF05::getOperationalMode() { return _mode; } ////////////////////////////////////////////////// // // MEASUREMENTS // uint32_t SRF05::getTime() { _lastTime = millis(); switch(_mode) { default: case SRF05_MODE_SINGLE: return _read(); case SRF05_MODE_AVERAGE: { float sum = 0; for (uint8_t s = 0; s < _count; s++) { sum += _read(); delayMicroseconds(_sampleInterval); } return round(sum / _count); } case SRF05_MODE_MEDIAN: { uint32_t samples[15]; for (uint8_t s = 0; s < _count; s++) { samples[s] = _read(); delayMicroseconds(_sampleInterval); } _insertSort(samples, _count); if (_count & 0x01) return samples[_count / 2]; return (samples[(_count + 1) / 2] + samples[_count / 2]) / 2; } case SRF05_MODE_RUN_AVERAGE: _value = (1 - _alpha) * _value + _alpha * _read(); return _value; } return 0; // should not happen } uint32_t SRF05::getMillimeter() { return _speedOfSound * getTime() * 0.5e-3; } float SRF05::getCentimeter() { return _speedOfSound * getTime() * 0.5e-4; } float SRF05::getMeter() { return _speedOfSound * getTime() * 0.5e-6; } float SRF05::getInch() { return _speedOfSound * getTime() * 1.9685e-5; } float SRF05::getFeet() { return _speedOfSound * getTime() * 1.64042e-6; } float SRF05::getYards() { return _speedOfSound * getTime() * 0.54681e-6; } // EXPERIMENTAL // distance in meters (single trip) float SRF05::determineSpeedOfSound(float distance, uint8_t count) { float sum = 0; if (count == 0) count = 1; while (count--) { sum += _read(); delayMicroseconds(_sampleInterval); } // sos = distance travelled forth and back in micrometer // divided by time in microseconds. float sos = (count * distance * 2e6) / sum; return sos; } void SRF05::setTriggerLength(uint8_t length) { _triggerLength = length; } uint8_t SRF05::getTriggerLength() { return _triggerLength; } uint32_t SRF05::lastTime() { return _lastTime; } float SRF05::calculateSpeedOfSound(float temperature, float humidity) { // interpolate // column RNH = 0%, from formula. float sos = 331.45 * sqrt(1 + temperature/273.15); // column RH = 100%, interpolation from spreadsheet float sos_100 = 332.392083694084 + 0.683791630591631 * temperature; // interpolate the humidity between these 2 if (humidity > 0) { sos += (sos_100 - sos) * humidity * 0.01; } return sos; } ////////////////////////////////////////////////// // // PRIVATE // uint32_t SRF05::_read() { // Send pulse pinMode(_trigger, OUTPUT); digitalWrite(_trigger, HIGH); delayMicroseconds(_triggerLength); digitalWrite(_trigger, LOW); // Wait for echo pinMode(_echo, INPUT); uint32_t duration = pulseIn(_echo, HIGH, 200000); // was 300000 (50+ meter) if (_correctionFactor == 1.0) { return duration; } return round(duration * _correctionFactor); } // for median void SRF05::_insertSort(uint32_t * array, uint8_t size) { uint8_t t, z; uint32_t temp; for (t = 1; t < size; t++) { z = t; temp = array[z]; while( (z > 0) && (temp < array[z - 1] )) { array[z] = array[z - 1]; z--; } array[z] = temp; yield(); } } // -- END OF FILE --