I've used a mini breadboard here to prioritize lightweight portability and ease of attaching to something moving, like a floating inflatable.
// Define pins
int trigPin = 11;
int echoPin = 10;
int REDPin = 6;
int GREENPin = 3;
int BLUEPin = 5;
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets trigPin as an Output
pinMode(echoPin, INPUT); // Sets echoPin as an Input
pinMode(REDPin, OUTPUT);
pinMode(GREENPin, OUTPUT);
pinMode(BLUEPin, OUTPUT);
Serial.begin(9600); //Prepares serial monitor
}
void loop() {
digitalWrite(trigPin, LOW); // Turns trigPin off
delayMicroseconds(2);
digitalWrite(trigPin, HIGH); // Turns trigPin on
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); // Reads echoPin, sets duration in microseconds
distance = duration*0.034/2; // Calculates distance based on speed of sound in air
Serial.print("Distance: "); // Sends distance to Serial Monitor
Serial.println(distance);
delay(50); // Choose frequency of readings
int BLUEbrightness = map(distance, 4, 50, 0, 20); //Remaps distance numbers to brightness
int REDbrightness = map(distance, 4, 50, 20, 0); // Remaps the inverse for another color
analogWrite(REDPin, REDbrightness);
analogWrite(BLUEPin, BLUEbrightness);
analogWrite(GREENPin, 0);
delay (50);
}
if (distance > 3000) {
analogWrite(REDPin, 0);
analogWrite(GREENPin, 0);
analogWrite(BLUEPin, 0);
}
else {...
I taught the vibration motor to report readings with a simple code of short buzzes to represent 10 centimeters and long buzzes to represent 1 meter (see code below). The vibration motor reports a reading, then begins again once finished reporting. The mini breadboard is better portable in the field. After flashing the code over, draw power from a power bank so you don't have to carry your laptop into the lake like I did.
// Define pins
int trigPin = 11;
int echoPin = 10;
int motorPin = 13;
long duration;
int distance;
//Program the length of pause between buzzes
int pause = 75;
//declare functions for one 10 cm buzz, one meter buzz, and a full stop
void decimeter() {
analogWrite(motorPin,0);
delay(pause);
analogWrite(motorPin,150);
delay(150); //make the decimeter buzz last 150 milliseconds
}
void meter() {
analogWrite(motorPin,0);
delay(pause);
analogWrite(motorPin,150);
delay(550); //make the meter buzz last 550 milliseconds
}
void fullstop() {
analogWrite(motorPin,0);
delay(1000); //make a full stop last 1000 milliseconds aka one second
}
//declare a function named hapticFeedback that takes an input of "n"
void hapticFeedback(int n) {
if (n < 100 && n >=80) { //if distance measured is less than 1 meter (within range)
int x = n/10; //divide distance into decimeters
for (int i = 0; i < x; i++) {// Loop to do something x times, starting at zero
decimeter(); //call the 10 cm buzz function
}
fullstop(); //full stop when done
}
else if (n >= 100 && n <= 1600) { //if distance is at least 1 meter
int x = n/100; //divide distance into meters
for (int i = 0; i < x; i++) {// Loop to do something x times, starting at zero
meter(); //call the meter buzz function
}
fullstop(); //full stop when done
}
else {
analogWrite(motorPin,0); //noise readings (out of range) give no feedback
}
}
void setup() {
pinMode(trigPin, OUTPUT); // Sets trigPin as an Output
pinMode(echoPin, INPUT); // Sets echoPin as an Input
pinMode(motorPin, OUTPUT); // Sets motorPin as an Output
Serial.begin(9600);
}
void loop() {
digitalWrite(trigPin, LOW); // Turns trigPin off
delayMicroseconds(2);
digitalWrite(trigPin, HIGH); // Turns trigPin on
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); // Reads echoPin, sets duration in microseconds
distance = duration*0.148/2; // Calculates distance based on speed of sound in water
Serial.print("Distance: "); // Sends distance to Serial Monitor
Serial.println(distance);
delay(50); // Choose frequency of readings
hapticFeedback(distance); //calls hapticFeedback function
}