SHOW:
|
|
- or go back to the newest paste.
1 | /* Arduino active sonar with metal detector style buzzer response */ | |
2 | ||
3 | // Libraries, external functions | |
4 | #include <NewPing_mod.h> | |
5 | #include <EEPROM_Int_ReadWrite> | |
6 | ||
7 | // Configuration constants | |
8 | const unsigned int BAUD_RATE = 9600; // Serial communication rate (Bd) | |
9 | const unsigned int STATUS_PIN = 13; // Pin identifier of internal LED | |
10 | const unsigned int BUZZ_PIN = 12; // Pin identifier of buzzer output | |
11 | const unsigned int SONAR_TRIG_PIN = 7; // Pin identifier of sonar output (can be the same as echo pin) | |
12 | const unsigned int SONAR_ECHO_PIN = 8; // Pin identifier of sonar input (can be the same as trigger pin) | |
13 | const unsigned int BUZZ_LENGTH = 80; // Duration of a buzz (ms) | |
14 | const unsigned int PULSE_LENGTH = 10; // Duration of outgoing trigger signal (us) | |
15 | const unsigned int PULSE_SAMPLES = 1; // Number of sonar pulses to take a statistical mean from (potentially interferes with buzz timing at high frequencies) | |
16 | const unsigned int PULSE_SKIP = 3; // Number of measurements to discard from start of execution, because the initial responses are off sometimes | |
17 | const unsigned int PULSE_DELAY = 500; // Amount of time between sonar queries (ms) | |
18 | const unsigned int MAX_DISTANCE = 900; // Maxium distance to probe for (cm) | |
19 | const unsigned int LOW_DISTANCE = 5 * US_ROUNDTRIP_CM; // Response time corresponding to a solid tone (us) | |
20 | const unsigned int HIGH_DISTANCE = 350 * US_ROUNDTRIP_CM; // Response time corresponding to highest buzz delay (us) | |
21 | const unsigned int MAX_BUZZ_DELAY = 5000; // Buzz delay to use with highest distance (ms) | |
22 | const unsigned int MIN_BUZZ_DELAY = 150; // Buzz delay to use with lowest distance (ms) | |
23 | const signed int RECORD_ADDR = 0; // Use this EEPROM address (occupies 2 bytes) to save maximum measured distance (negative value to disable) | |
24 | const bool BUZZ_ENABLED = true; // Use the buzzer to report distance metal detector style | |
25 | const bool STATUS_ENABLED = true; // Use the status led in addition to / instead of buzzer beeps | |
26 | ||
27 | // Internal constants and variables | |
28 | const float DISTANCE_RANGE = HIGH_DISTANCE - LOW_DISTANCE; // Range in which to vary buzz delay (us) | |
29 | const unsigned int BUZZ_DELAY_RANGE = MAX_BUZZ_DELAY - MIN_BUZZ_DELAY; // Range of values for buzz delay (ms) | |
30 | unsigned long buzzDelay = 0; // Delay between buzzes (ms) | |
31 | unsigned long lastBuzz = 1; // Historical timestamp of most recent buzz (ms) | |
32 | unsigned long nextPulse = 1; // Timestamp for next sonar pulse (ms) | |
33 | unsigned long pulseCount = 0; // Number of queries performed from start of execution | |
34 | unsigned int recordDistance = 0; // Highest distance measured (us) | |
35 | NewPing sonar(SONAR_TRIG_PIN, SONAR_ECHO_PIN, MAX_DISTANCE); // NewPing sonar interface | |
36 | ||
37 | void setup() { | |
38 | ||
39 | // Set up output pins | |
40 | pinMode(STATUS_PIN, OUTPUT); | |
41 | pinMode(BUZZ_PIN, OUTPUT); | |
42 | ||
43 | // Make sure outputs are low | |
44 | digitalWrite(STATUS_PIN, LOW); | |
45 | digitalWrite(BUZZ_PIN, LOW); | |
46 | ||
47 | // Start serial connection | |
48 | Serial.begin(BAUD_RATE); | |
49 | ||
50 | // Read and report current record | |
51 | if (RECORD_ADDR > -1) { | |
52 | recordDistance = EEPROMReadInt(RECORD_ADDR); | |
53 | if (recordDistance > 0xFF00) recordDistance = 0; // Reset uninitialized or faulty value | |
54 | Serial.print("Current record is "); | |
55 | outputDistance(recordDistance); | |
56 | Serial.println(); | |
57 | } | |
58 | ||
59 | } | |
60 | ||
61 | void loop() { | |
62 | ||
63 | // Read current Arduino timestamp | |
64 | unsigned long arduinoTime = millis(); | |
65 | ||
66 | // Start a new buzz (solid tone) | |
67 | if (buzzDelay == 1 && digitalRead(BUZZ_PIN) == LOW) { | |
68 | startBuzz(); | |
69 | ||
70 | // Start a new buzz (single beep) | |
71 | } else if (buzzDelay != 0 && arduinoTime > lastBuzz + buzzDelay) { | |
72 | ||
73 | startBuzz(); | |
74 | ||
75 | // Schedule the buzz end and next buzz | |
76 | NewPing::timer_ms(BUZZ_LENGTH, stopBuzz); | |
77 | lastBuzz = arduinoTime; | |
78 | ||
79 | } | |
80 | ||
81 | // Query the ultrasonic sensor | |
82 | if (nextPulse != 0 && arduinoTime > nextPulse) { | |
83 | ||
84 | // Read and filter the sensor data | |
85 | unsigned int responseTime = sonar.ping_median(PULSE_SAMPLES); | |
86 | ||
87 | // Update pulse count and proceed only if high enough | |
88 | if (++pulseCount > PULSE_SKIP) { | |
89 | ||
90 | // Report values to the serial port | |
91 | Serial.print("Measured "); | |
92 | outputDistance(responseTime); | |
93 | Serial.print(" ("); | |
94 | Serial.print(pulseCount); | |
95 | Serial.println(")"); | |
96 | ||
97 | // Update and report record | |
98 | if (RECORD_ADDR > -1 && responseTime > recordDistance) { | |
99 | recordDistance = responseTime; | |
100 | EEPROMWriteInt(RECORD_ADDR, responseTime); | |
101 | Serial.print("Wrote new record to ROM: "); | |
102 | outputDistance(recordDistance); | |
103 | Serial.println(); | |
104 | } | |
105 | ||
106 | // Adjust buzz timing | |
107 | boolean solidTone = (buzzDelay == 1); | |
108 | if (responseTime == 0) { | |
109 | buzzDelay = 0; | |
110 | } else { | |
111 | if (responseTime <= LOW_DISTANCE) { | |
112 | buzzDelay = 1; | |
113 | } | |
114 | if (responseTime > LOW_DISTANCE && responseTime <= HIGH_DISTANCE) { | |
115 | buzzDelay = (responseTime - LOW_DISTANCE) / DISTANCE_RANGE * BUZZ_DELAY_RANGE + MIN_BUZZ_DELAY; | |
116 | } | |
117 | if (responseTime > HIGH_DISTANCE) { | |
118 | buzzDelay = MAX_BUZZ_DELAY; | |
119 | } | |
120 | } | |
121 | if (solidTone && buzzDelay != 1) stopBuzz(); | |
122 | ||
123 | } else { | |
124 | Serial.print("Skipped measurement "); | |
125 | Serial.println(pulseCount); | |
126 | } | |
127 | ||
128 | // Schedule the next pulse | |
129 | nextPulse = arduinoTime + PULSE_DELAY; | |
130 | ||
131 | } | |
132 | ||
133 | } | |
134 | ||
135 | // Activate buzzer | |
136 | void startBuzz() { | |
137 | if (BUZZ_ENABLED) digitalWrite(BUZZ_PIN, HIGH); | |
138 | if (STATUS_ENABLED) digitalWrite(STATUS_PIN, HIGH); | |
139 | } | |
140 | ||
141 | // Stop an ongoing buzz | |
142 | void stopBuzz() { | |
143 | digitalWrite(BUZZ_PIN, LOW); | |
144 | digitalWrite(STATUS_PIN, LOW); | |
145 | NewPing::timer_stop(); | |
146 | } | |
147 | ||
148 | // Output response time in human-readable format | |
149 | - | void outputDistance(int responseTime) { |
149 | + | String outputDistance(int responseTime) { |
150 | Serial.print(responseTime); | |
151 | Serial.print(' '); | |
152 | Serial.write(181); // Micro sign in ISO-8859-1 | |
153 | Serial.print("s / "); | |
154 | Serial.print(sonar.convert_cm(responseTime)); | |
155 | Serial.print(" cm"); | |
156 | } |