Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
initial commit of my first try
  • Loading branch information
d03n3rfr1tz3 committed Jul 22, 2020
1 parent aeefdcc commit a1c051a
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 3 deletions.
33 changes: 33 additions & 0 deletions .gitignore
Expand Up @@ -50,3 +50,36 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf

#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
*.opensdf
*.unsuccessfulbuild
ipch/
[Oo]bj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
/bots/DiskCache
/dropbox/DiskCache
/minecraft/DiskCache
/.vs
/packages/*/
Binary file added HC-SR04.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
MIT License
The MIT License (MIT)

Copyright (c) 2020 Dirk Sarodnick

Expand Down
40 changes: 38 additions & 2 deletions README.md
@@ -1,2 +1,38 @@
# arduino-hc-sr04
Library for measuring distance with the HC-SR04 UltraSonic Sensor, by utilizing temperature correction and multiple echo pins in parallel.
# Arduino/ESP8266/ESP32 library for HC-SR04 ultrasonic distance sensor.

This library is used for measuring distance with the HC-SR04, which is an ultrasonic sensor that measures distances from 2 to 400cm. My library features a temperature correction and can utilize one trigger pin with multiple echo pins in parallel. I based this library on two other libraries.
1. https://github.com/Martinsos/arduino-lib-hc-sr04 --> I basically used the temperature calculation
2. https://github.com/gamegine/HCSR04-ultrasonic-sensor-lib --> I basically used the idea of using one trigger and multiple echos. But instead of measuring them in series, I tried to do that in parallel.

![HC-SR04](/HC-SR04.png)

## Usage


## Example

```c
#include <HCSR04.h>

int triggerPin = 21;
int* echoPins = new int[2] { 12, 13 };

void setup () {
Serial.begin(9600);
HCSR04.begin(triggerPin, echoPins);
}

void loop () {
size_t size = sizeof(echoPins)/sizeof(echoPins[0]);
double* distances = HCSR04.measureDistanceCm();

for (int i = 0; i < size; i++) {
Serial.print(i);
Serial.print(": ");
Serial.print(distances[i]);
Serial.println("---");
}

delay(500);
}
```
23 changes: 23 additions & 0 deletions examples/HC-SR04 Simple/HC-SR04 Simple.ino
@@ -0,0 +1,23 @@
#include <HCSR04.h>

int triggerPin = 21;
int* echoPins = new int[2] { 12, 13 };

void setup () {
Serial.begin(9600);
HCSR04.begin(triggerPin, echoPins);
}

void loop () {
size_t size = sizeof(echoPins)/sizeof(echoPins[0]);
double* distances = HCSR04.measureDistanceCm();

for (int i = 0; i < size; i++) {
Serial.print(i);
Serial.print(": ");
Serial.print(distances[i]);
Serial.println("---");
}

delay(500);
}
3 changes: 3 additions & 0 deletions keywords.txt
@@ -0,0 +1,3 @@
HCSR04 KEYWORD1
measureDistanceMm KEYWORD2
measureDistanceCm KEYWORD3
9 changes: 9 additions & 0 deletions library.properties
@@ -0,0 +1,9 @@
name=HC-SR04
version=1.0.0
author=Dirk Sarodnick <dirk.sarodnick@googlemail.com>
maintainer=Dirk Sarodnick <dirk.sarodnick@googlemail.com>
sentence=Library for HC-SR04 ultrasonic distance sensor.
paragraph=You can measure distance in microseconds, millimeters and centimeters.
category=Sensors
url=https://github.com/d03n3rfr1tz3/HC-SR04
architectures=*
217 changes: 217 additions & 0 deletions src/HCSR04.cpp
@@ -0,0 +1,217 @@
/*
HCSR04 - Library for arduino, for HC-SR04 ultrasonic distance sensor.
Created by Dirk Sarodnick, 2020.
*/

#include "Arduino.h"
#include "HCSR04.h"

HCSR04Sensor::HCSR04Sensor() {}

void HCSR04Sensor::begin(int triggerPin, int* echoPins) {
this->triggerPin = triggerPin;
this->echoPins = echoPins;
this->timeout = 100000;
this->unlock = false;

size_t size = sizeof(echoPins)/sizeof(echoPins[0]);
this->triggerTimes = new unsigned long[size];
this->echoTimes = new unsigned long[size];
}

void HCSR04Sensor::begin(int triggerPin, int* echoPins, int timeout, bool unlock) {
this->triggerPin = triggerPin;
this->timeout = timeout;
this->unlock = unlock;

size_t size = sizeof(echoPins)/sizeof(echoPins[0]);
this->triggerTimes = new unsigned long[size];
this->echoTimes = new unsigned long[size];

this->echoPins = new int[size];
for (int i = 0; i < size; i++) {
this->echoPins[i] = digitalPinToInterrupt(echoPins[i]);
}
}

long* HCSR04Sensor::measureMicroseconds() {
size_t size = sizeof(this->echoPins)/sizeof(this->echoPins[0]);

// Unlock sensors that are possibly in a locked state, if this feature is enabled.
if (this->unlock) this->unlockSensors();

// Make sure that trigger pin is LOW.
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);

// Hold trigger for 10 microseconds, which is signal for sensor to measure distance.
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);

// Attach interrupts to echo pins for the starting point
for (int i = 0; i < size; i++) {
switch (i) {
case 0: attachInterrupt(this->echoPins[i], &triggerInterrupt0, RISING); break;
case 1: attachInterrupt(this->echoPins[i], &triggerInterrupt1, RISING); break;
case 2: attachInterrupt(this->echoPins[i], &triggerInterrupt2, RISING); break;
case 3: attachInterrupt(this->echoPins[i], &triggerInterrupt3, RISING); break;
case 4: attachInterrupt(this->echoPins[i], &triggerInterrupt4, RISING); break;
case 5: attachInterrupt(this->echoPins[i], &triggerInterrupt5, RISING); break;
case 6: attachInterrupt(this->echoPins[i], &triggerInterrupt6, RISING); break;
case 7: attachInterrupt(this->echoPins[i], &triggerInterrupt7, RISING); break;
case 8: attachInterrupt(this->echoPins[i], &triggerInterrupt8, RISING); break;
case 9: attachInterrupt(this->echoPins[i], &triggerInterrupt9, RISING); break;
}
}

// Wait until all echos are returned or timed out.
while(1) {
delayMicroseconds(1);

bool finished = true;
bool waiting = true;

long currentMicros = micros();
for (int i = 0; i < size; i++) {
waiting &= currentMicros - this->triggerTimes[i] < this->timeout;

if (this->triggerTimes[i] > 0) {
switch (i) {
case 0: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt0, FALLING); break;
case 1: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt1, FALLING); break;
case 2: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt2, FALLING); break;
case 3: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt3, FALLING); break;
case 4: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt4, FALLING); break;
case 5: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt5, FALLING); break;
case 6: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt6, FALLING); break;
case 7: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt7, FALLING); break;
case 8: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt8, FALLING); break;
case 9: detachInterrupt(this->echoPins[i]); attachInterrupt(this->echoPins[i], &echoInterrupt9, FALLING); break;
}
} else finished &= false;

if (this->echoTimes[i] > 0) {
switch (i) {
case 0: detachInterrupt(this->echoPins[i]); break;
case 1: detachInterrupt(this->echoPins[i]); break;
case 2: detachInterrupt(this->echoPins[i]); break;
case 3: detachInterrupt(this->echoPins[i]); break;
case 4: detachInterrupt(this->echoPins[i]); break;
case 5: detachInterrupt(this->echoPins[i]); break;
case 6: detachInterrupt(this->echoPins[i]); break;
case 7: detachInterrupt(this->echoPins[i]); break;
case 8: detachInterrupt(this->echoPins[i]); break;
case 9: detachInterrupt(this->echoPins[i]); break;
}
} else finished &= false;
}

if (!waiting || finished) break;
}

// Determine the durations of each sensor.
long* results = new long[size];
for (int i = 0; i < size; i++) {
results[i] = this->echoTimes[i] - this->triggerTimes[i];

this->triggerTimes[i] = 0;
this->echoTimes[i] = 0;
}

return results;
}

double* HCSR04Sensor::measureDistanceMm() {
return measureDistanceMm(19.307);
}

double* HCSR04Sensor::measureDistanceMm(float temperature) {
double speedOfSoundInMmPerMs = 331.3 + 0.0606 / 1000 * temperature; // Cair ≈ (331.3 + 0.606 ⋅ ϑ) m/s
size_t size = sizeof(this->echoPins)/sizeof(this->echoPins[0]);
long* results = measureMicroseconds();

// Calculate the distance in mm for each result.
for (int i = 0; i < size; i++) {
double distanceCm = results[i] / 2.0 * speedOfSoundInMmPerMs;
if (distanceCm == 0 || distanceCm > 400) {
results[i] = -1.0;
} else {
results[i] = distanceCm;
}
}
}

double* HCSR04Sensor::measureDistanceCm() {
return measureDistanceCm(19.307);
}

double* HCSR04Sensor::measureDistanceCm(float temperature) {
double speedOfSoundInCmPerMs = 331.3 + 0.606 / 1000 * temperature; // Cair ≈ (331.3 + 0.606 ⋅ ϑ) m/s
size_t size = sizeof(this->echoPins)/sizeof(this->echoPins[0]);
long* results = measureMicroseconds();

// Calculate the distance in cm for each result.
for (int i = 0; i < size; i++) {
double distanceCm = results[i] / 2.0 * speedOfSoundInCmPerMs;
if (distanceCm == 0 || distanceCm > 400) {
results[i] = -1.0;
} else {
results[i] = distanceCm;
}
}
}

void HCSR04Sensor::unlockSensors() {
bool hasLocked = false;
size_t size = sizeof(this->echoPins)/sizeof(this->echoPins[0]);

// Check if any sensor is in a locked state and unlock it if necessary.
for (int i = 0; i < size; i++) {
if (digitalRead(this->echoPins[i]) == LOW) continue;
pinMode(this->echoPins[i], OUTPUT);
digitalWrite(this->echoPins[i], LOW);
hasLocked = true;
}

if (hasLocked) delay(50);

// Revert the pinMode after potential unlocking.
for (int i = 0; i < size; i++) {
pinMode(this->echoPins[i], INPUT);
}

if (hasLocked) delay(50);
}

void HCSR04Sensor::triggerInterrupt(int index) {
this->triggerTimes[index] = micros();
}

void HCSR04Sensor::echoInterrupt(int index) {
this->echoTimes[index] = micros();
}

void HCSR04Sensor::triggerInterrupt0() { HCSR04.triggerInterrupt(0); }
void HCSR04Sensor::triggerInterrupt1() { HCSR04.triggerInterrupt(1); }
void HCSR04Sensor::triggerInterrupt2() { HCSR04.triggerInterrupt(2); }
void HCSR04Sensor::triggerInterrupt3() { HCSR04.triggerInterrupt(3); }
void HCSR04Sensor::triggerInterrupt4() { HCSR04.triggerInterrupt(4); }
void HCSR04Sensor::triggerInterrupt5() { HCSR04.triggerInterrupt(5); }
void HCSR04Sensor::triggerInterrupt6() { HCSR04.triggerInterrupt(6); }
void HCSR04Sensor::triggerInterrupt7() { HCSR04.triggerInterrupt(7); }
void HCSR04Sensor::triggerInterrupt8() { HCSR04.triggerInterrupt(8); }
void HCSR04Sensor::triggerInterrupt9() { HCSR04.triggerInterrupt(9); }

void HCSR04Sensor::echoInterrupt0() { HCSR04.echoInterrupt(0); }
void HCSR04Sensor::echoInterrupt1() { HCSR04.echoInterrupt(1); }
void HCSR04Sensor::echoInterrupt2() { HCSR04.echoInterrupt(2); }
void HCSR04Sensor::echoInterrupt3() { HCSR04.echoInterrupt(3); }
void HCSR04Sensor::echoInterrupt4() { HCSR04.echoInterrupt(4); }
void HCSR04Sensor::echoInterrupt5() { HCSR04.echoInterrupt(5); }
void HCSR04Sensor::echoInterrupt6() { HCSR04.echoInterrupt(6); }
void HCSR04Sensor::echoInterrupt7() { HCSR04.echoInterrupt(7); }
void HCSR04Sensor::echoInterrupt8() { HCSR04.echoInterrupt(8); }
void HCSR04Sensor::echoInterrupt9() { HCSR04.echoInterrupt(9); }

HCSR04Sensor HCSR04;

0 comments on commit a1c051a

Please sign in to comment.