# Distance Detector¶

Warning

This journal entry is the combination of analog IO, LEDs, ultrasonic sensors and shift registers

## Parts Used¶

• 7 Leds

• 1 Buzzer

• 1 shift register

• 1 ultrasonic sensor

• 1 2000Ω resistor

• 20 jumper wires

• 1 arduino uno

## Time Spent¶

Approximately 12 hours. Distrubuted highly unevenly over the range of 7 days.

## Key Points¶

• The program can run about 3 times faster if it does not write anything to Serial

• Ultrasonic Sensor is not reliable all the time. To elimate inaccurate results, a smoothing algorithm is necessary.

• There is a specialized library named newping for ultrasonic sensor

## Smoothing algorithm¶

In this project, I wrote a smoothing algorithm to stay away from inaccuate ultrasonic sensor data while minimize the delay. At first, I tried to use moving average to smooth the data. However, it causes a perceivable amount of delay (approximately 0.5 seconds) in the output.

The final algorithm works as follow

1. Read a new distance in cm from sensor

2. If the distance is greater than 255, use 255 instead

3. Let m be the median of last 5 inputs

4. Decide the margin of error with this formula $$\frac{20}{(\log_{2}(m))^2}\times 100\%$$

5. If the new distance beyond margin of error, output m, else output new distance.

6. Goto 1

## The Code¶

#include <math.h>

int potPin = 0;
int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

int leds = 0;

const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
int distance;

#define dataSize 5

int data[dataSize];
int inputLoc = 0;

void setup()
{
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
for (int i = 0; i < dataSize; i++) data[i] = calculateDistance();

Serial.begin(9600);
}

void loop()
{

leds = 0;

distance = correctedOutput(20);

if (distance > 64) {
leds = 0b10000000;
} else {

distance /= 8;
bitSet(leds, distance);

}
delay(50)

}

int correctedOutput(float threshold) {
int r= calculateDistance();
int newReading = r>256? 256:r ;
int corrected;
int m = median(data, dataSize);

float scaling = (threshold / pow((log(m) / log(2)),2));

inputLoc++;
if (inputLoc == dataSize) inputLoc = 0;

if ( (newReading > m + scaling*m ) or (newReading < m - scaling*m) )
{
corrected = m;
} else {

}

#define DEBUG

#ifdef DEBUG

Serial.print("| Input value: ");
Serial.print(r);
Serial.print(" | Corrected to: ");
Serial.print(corrected);
Serial.print(" | Margin: +/- ");
Serial.print(scaling*100);

Serial.print("% | Valid Range for this input: ");
Serial.print (m - scaling*m);
Serial.print(" to ");
Serial.print( scaling*m + m);
Serial.print(" | Input accepted: ");

#endif

return corrected;
}

{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, leds);
digitalWrite(latchPin, HIGH);
}

int calculateDistance() {
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance = duration * 0.034 / 2;
// Prints the distance on the Serial Monitor
return distance;
}

int median(const int * arr, int len) {

int newArr[len];
for (int j = 0; j < len; j++) { //Duplicate arr
newArr[j] = arr[j];
}

//Begin BubbleSort

bool sorted;
int tmp;
do {
sorted = true;
for (int i=0; i < len - 1; i++) {
if (newArr[i] < newArr[i + 1]) { //swap two values
tmp = newArr[i];
newArr[i] = newArr[i + 1];
newArr[i + 1] = tmp;
sorted = false;
}
}
} while (!sorted);
//End BubbleSort newArr
return newArr[len/2];
}


## Major Issues Encontered¶

1. The first time to wire the shift register was really troublesome. Initially, I forgot to ground the shift register; it was working, but became super-hot. After that, the code was not working as desired. I soon realized that I had the the entire right side connections reversed. Everything was straightforward after I learned how the shiftOut function works.

2. Memory Overflow. Because arduino uno has only 2 KiB of RAM, it is possible to overflow the memory if not careful. In such case, the program stops working (gets stucked at a data value) after a working for a while. One temporary solution is to unplug the arduino for about 10 seconds, so the RAM is cleared. In my case, I did not use the array pointer correctly as I am a new programmer to C, so the obesolete data are not garbage collected but stay in the memory for as long as it still gets power. Everything works fine after I found the programming error and fixed it.

3. Not always reliable data from ultrasonic sensor. Solution: smoothing algorithm.