#define ledr PB1
#define ledy PB5
#define trig PB0
#define echo PB7
#define buz PB4
#define SW2 PB6
// segments
#define segA PA0
#define segB PA1
#define segC PA2
#define segD PA3
#define segE PA4
#define segF PA5
#define segG PA6
#define segDP PA7
// digits
#define DIG1 PC15
#define DIG2 PA8
const byte pattern[10][7] = {
{0,0,0,0,0,0,1}, //0
{1,0,0,1,1,1,1}, //1
{0,0,1,0,0,1,0}, //2
{0,0,0,0,1,1,0}, //3
{1,0,0,1,1,0,0}, //4
{0,1,0,0,1,0,0}, //5
{0,1,0,0,0,0,0}, //6
{0,0,0,1,1,1,1}, //7
{0,0,0,0,0,0,0}, //8
{0,0,0,0,1,0,0} //9
};
bool lastSwitchState = HIGH;
int stableDistance = -1;
int lastPrintedDist = -1;
void setSegments(int digit){
digitalWrite(segA, pattern[digit][0]);
digitalWrite(segB, pattern[digit][1]);
digitalWrite(segC, pattern[digit][2]);
digitalWrite(segD, pattern[digit][3]);
digitalWrite(segE, pattern[digit][4]);
digitalWrite(segF, pattern[digit][5]);
digitalWrite(segG, pattern[digit][6]);
}
void showDistance(int cm){
if (cm < 0 || cm > 999) return;
int left = cm / 100;
int right = (cm % 100) / 10;
digitalWrite(DIG2, LOW);
digitalWrite(DIG1, HIGH);
setSegments(left);
delay(4);
digitalWrite(DIG1, LOW);
digitalWrite(DIG2, HIGH);
setSegments(right);
delay(4);
}
int rawPing() {
digitalWrite(trig, LOW);
delayMicroseconds(4);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
long dur = pulseIn(echo, HIGH, 38000UL);
if (dur == 0) return -1;
int d = (int)(dur * 0.034 / 2);
if (d < 2 || d > 400) return -1;
return d;
}
int stablePing() {
const int N = 5;
int readings[N];
int valid = 0;
for (int i = 0; i < N; i++) {
int r = rawPing();
if (r > 0) readings[valid++] = r;
delay(62);
}
if (valid < 3) return -1;
for (int i = 0; i < valid - 1; i++)
for (int j = i + 1; j < valid; j++)
if (readings[j] < readings[i]) {
int tmp = readings[i];
readings[i] = readings[j];
readings[j] = tmp;
}
int sum = 0;
int count = 0;
for (int i = 1; i < valid - 1; i++) {
sum += readings[i];
count++;
}
return (count > 0) ? (sum / count) : -1;
}
void warmUp() {
for (int i = 0; i < 3; i++) {
rawPing();
delay(65);
}
}
void setup() {
Serial.begin(115200);
pinMode(ledr, OUTPUT);
pinMode(ledy, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
pinMode(buz, OUTPUT);
pinMode(SW2, INPUT_PULLUP);
pinMode(segA, OUTPUT);
pinMode(segB, OUTPUT);
pinMode(segC, OUTPUT);
pinMode(segD, OUTPUT);
pinMode(segE, OUTPUT);
pinMode(segF, OUTPUT);
pinMode(segG, OUTPUT);
pinMode(segDP, OUTPUT);
pinMode(DIG1, OUTPUT);
pinMode(DIG2, OUTPUT);
digitalWrite(trig, LOW);
}
void loop() {
bool currentSwitch = digitalRead(SW2);
if (lastSwitchState == HIGH && currentSwitch == LOW) {
noTone(buz);
delayMicroseconds(200);
warmUp();
stableDistance = -1;
lastPrintedDist = -1;
}
lastSwitchState = currentSwitch;
if (currentSwitch == HIGH) {
noTone(buz);
digitalWrite(ledr, LOW);
digitalWrite(ledy, LOW);
digitalWrite(LED_BUILTIN, LOW);
showDistance(0);
delay(200);
return;
}
noTone(buz);
delayMicroseconds(200);
int measured = stablePing();
if (measured > 0) {
if (abs(measured - stableDistance) > 2) {
stableDistance = measured;
}
}
else {
stableDistance = -1;
}
if (stableDistance != lastPrintedDist) {
if (stableDistance > 0) {
Serial.print("Distance: ");
Serial.print(stableDistance);
Serial.println(" cm");
}
else {
Serial.println("Distance: out of range");
}
lastPrintedDist = stableDistance;
}
showDistance(stableDistance);
if (stableDistance < 0) {
digitalWrite(ledr, LOW);
digitalWrite(ledy, LOW);
digitalWrite(LED_BUILTIN, HIGH);
}
else if (stableDistance < 30) {
digitalWrite(ledr, HIGH);
digitalWrite(ledy, LOW);
digitalWrite(LED_BUILTIN, LOW);
tone(buz, 880);
delay(200);
}
else if (stableDistance < 120) {
long interval = map(stableDistance, 30, 120, 100, 800);
digitalWrite(ledr,LOW);
digitalWrite(ledy, HIGH);
digitalWrite(LED_BUILTIN, LOW);
tone(buz, 440);
delay(80);
noTone(buz);
delay(interval);
}
else {
digitalWrite(ledr,LOW);
digitalWrite(ledy,LOW);
digitalWrite(LED_BUILTIN, HIGH);
}
}