TinkerCAD
Start by building and testing the circuit here: Ultrasonic Basics.
Upload the following to your Arduino
int trigPin = 10;
int echoPin = 11;
long duration, cm, inches;
volatile int n = 1; // 1..100
long history[100] = {0};
void setup() {
Serial.begin(9600);
Serial.setTimeout(1); // IMPORTANT: don't block waiting for digits
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
long average(long s) {
// shift right (keep newest at [0])
for (int i = 99; i >= 1; i--) {
history[i] = history[i - 1];
}
history[0] = s;
long sum = 0;
for (int i = 0; i < n; i++) sum += history[i];
return sum / n;
}
void loop() {
// --- RECEIVE n (non-blocking) ---
if (Serial.available() > 0) {
int newN = Serial.parseInt(); // reads quickly due to timeout=1ms
if (newN >= 1 && newN <= 100) n = newN;
// flush rest of line (newline etc.)
while (Serial.available() > 0) Serial.read();
}
// --- MEASURE ---
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
duration = pulseIn(echoPin, HIGH);
long avg = average(duration);
cm = (avg / 2.0) / 29.1;
inches = (avg / 2.0) / 74.0;
// --- SEND ---
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm, n=");
Serial.println(n);
delay(20); // ~50 Hz stream; remove/adjust as you like
}
Upload the following to Processing
import processing.serial.*;
Serial port;
int historyLen = 600;
float[] y = new float[historyLen];
int n = 0;
float lastCm = 0;
float pad = 5;
// --- slider layout ---
int sliderX = 70;
int sliderW = 380;
int sliderH = 40; // reserved area height at bottom
int sliderY; // computed from height
int knobX = sliderX;
boolean dragging = false;
int value = 1; // 1–100
int lastSent = -1;
void setup() {
size(900, 450);
println(Serial.list());
int portIndex = 3; // <-- CHANGE THIS
port = new Serial(this, Serial.list()[portIndex], 9600);
port.bufferUntil('\n');
sliderY = height - 20; // slider line y
knobX = sliderX; // start at value=1
}
void draw() {
background(255);
// --- graph area (leave space for slider) ---
int left = 50, top = 30, right = width - 30, bottom = height - sliderH - 20;
int gw = right - left, gh = bottom - top;
// axes
stroke(0);
noFill();
rect(left, top, gw, gh);
fill(0);
text("Distance (cm)", 10, 20);
text("Time →", width/2, height - 5);
text(nf(lastCm, 0, 1) + " cm", left + 10, top - 5);
// --- slider ---
drawSlider();
// no data yet
if (n == 0) {
fill(0);
text("Waiting for data...", left + 10, top + 20);
return;
}
// autoscale from data
float ymin = y[0], ymax = y[0];
for (int i = 1; i < n; i++) {
if (y[i] < ymin) ymin = y[i];
if (y[i] > ymax) ymax = y[i];
}
if (abs(ymax - ymin) < 0.001) { ymax += 1; ymin -= 1; }
ymin -= pad; ymax += pad;
// Y ticks
stroke(220);
fill(0);
textAlign(RIGHT, CENTER);
for (int i = 0; i <= 4; i++) {
float v = lerp(ymin, ymax, i/4.0);
float yy = map(v, ymin, ymax, bottom, top);
line(left, yy, right, yy);
text(nf(v, 0, 1), left - 5, yy);
}
textAlign(LEFT, BASELINE);
// plot
stroke(0);
noFill();
beginShape();
for (int i = 0; i < n; i++) {
float x = map(i, 0, historyLen - 1, left, right);
float yy = map(y[i], ymin, ymax, bottom, top);
vertex(x, yy);
}
endShape();
}
void drawSlider() {
int lineY = height - 20;
stroke(0);
line(sliderX, lineY, sliderX + sliderW, lineY);
// knob
fill(0);
ellipse(knobX, lineY, 14, 14);
// map knob to value (1..100)
value = int(map(knobX, sliderX, sliderX + sliderW, 1, 100));
value = constrain(value, 1, 100);
fill(0);
text("n = " + value + " (send on release)", sliderX, lineY - 12);
}
void serialEvent(Serial p) {
String line = p.readStringUntil('\n');
if (line == null) return;
line = trim(line);
if (line.length() == 0) return;
try {
// Find "... <number>cm ..." anywhere in the line
int cmPos = line.indexOf("cm");
if (cmPos < 0) return;
// Walk backwards from 'c' to find start of the number
int end = cmPos; // index of 'c' in "cm"
int start = end - 1;
while (start >= 0) {
char ch = line.charAt(start);
if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-' ) start--;
else break;
}
start += 1;
if (start >= end) return;
float cm = float(line.substring(start, end));
lastCm = cm;
if (n < historyLen) {
y[n++] = cm;
} else {
arrayCopy(y, 1, y, 0, historyLen - 1);
y[historyLen - 1] = cm;
}
} catch (Exception e) {
// ignore malformed lines
}
}
void mousePressed() {
int lineY = height - 20;
if (dist(mouseX, mouseY, knobX, lineY) < 10) dragging = true;
}
void mouseDragged() {
if (dragging) knobX = constrain(mouseX, sliderX, sliderX + sliderW);
}
void mouseReleased() {
if (!dragging) return;
dragging = false;
// send once, and only if changed
if (value != lastSent) {
port.write(value + "\n");
lastSent = value;
println("Sent n=" + value);
}
}