Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Arduino active sonar with metal detector style buzzer response */
- // Libraries, external functions
- #include <NewPing_mod.h>
- #include <EEPROM_Int_ReadWrite>
- // Configuration constants
- const unsigned int BAUD_RATE = 9600; // Serial communication rate (Bd)
- const unsigned int STATUS_PIN = 13; // Pin identifier of internal LED
- const unsigned int BUZZ_PIN = 12; // Pin identifier of buzzer output
- const unsigned int SONAR_TRIG_PIN = 7; // Pin identifier of sonar output (can be the same as echo pin)
- const unsigned int SONAR_ECHO_PIN = 8; // Pin identifier of sonar input (can be the same as trigger pin)
- const unsigned int BUZZ_LENGTH = 80; // Duration of a buzz (ms)
- const unsigned int PULSE_LENGTH = 10; // Duration of outgoing trigger signal (us)
- const unsigned int PULSE_SAMPLES = 1; // Number of sonar pulses to take a statistical mean from (potentially interferes with buzz timing at high frequencies)
- const unsigned int PULSE_SKIP = 3; // Number of measurements to discard from start of execution, because the initial responses are off sometimes
- const unsigned int PULSE_DELAY = 500; // Amount of time between sonar queries (ms)
- const unsigned int MAX_DISTANCE = 900; // Maxium distance to probe for (cm)
- const unsigned int LOW_DISTANCE = 5 * US_ROUNDTRIP_CM; // Response time corresponding to a solid tone (us)
- const unsigned int HIGH_DISTANCE = 350 * US_ROUNDTRIP_CM; // Response time corresponding to highest buzz delay (us)
- const unsigned int MAX_BUZZ_DELAY = 5000; // Buzz delay to use with highest distance (ms)
- const unsigned int MIN_BUZZ_DELAY = 150; // Buzz delay to use with lowest distance (ms)
- const signed int RECORD_ADDR = 0; // Use this EEPROM address (occupies 2 bytes) to save maximum measured distance (negative value to disable)
- const bool BUZZ_ENABLED = true; // Use the buzzer to report distance metal detector style
- const bool STATUS_ENABLED = true; // Use the status led in addition to / instead of buzzer beeps
- // Internal constants and variables
- const float DISTANCE_RANGE = HIGH_DISTANCE - LOW_DISTANCE; // Range in which to vary buzz delay (us)
- const unsigned int BUZZ_DELAY_RANGE = MAX_BUZZ_DELAY - MIN_BUZZ_DELAY; // Range of values for buzz delay (ms)
- unsigned long buzzDelay = 0; // Delay between buzzes (ms)
- unsigned long lastBuzz = 1; // Historical timestamp of most recent buzz (ms)
- unsigned long nextPulse = 1; // Timestamp for next sonar pulse (ms)
- unsigned long pulseCount = 0; // Number of queries performed from start of execution
- unsigned int recordDistance = 0; // Highest distance measured (us)
- NewPing sonar(SONAR_TRIG_PIN, SONAR_ECHO_PIN, MAX_DISTANCE); // NewPing sonar interface
- void setup() {
- // Set up output pins
- pinMode(STATUS_PIN, OUTPUT);
- pinMode(BUZZ_PIN, OUTPUT);
- // Make sure outputs are low
- digitalWrite(STATUS_PIN, LOW);
- digitalWrite(BUZZ_PIN, LOW);
- // Start serial connection
- Serial.begin(BAUD_RATE);
- // Read and report current record
- if (RECORD_ADDR > -1) {
- recordDistance = EEPROMReadInt(RECORD_ADDR);
- if (recordDistance > 0xFF00) recordDistance = 0; // Reset uninitialized or faulty value
- Serial.print("Current record is ");
- outputDistance(recordDistance);
- Serial.println();
- }
- }
- void loop() {
- // Read current Arduino timestamp
- unsigned long arduinoTime = millis();
- // Start a new buzz (solid tone)
- if (buzzDelay == 1 && digitalRead(BUZZ_PIN) == LOW) {
- startBuzz();
- // Start a new buzz (single beep)
- } else if (buzzDelay != 0 && arduinoTime > lastBuzz + buzzDelay) {
- startBuzz();
- // Schedule the buzz end and next buzz
- NewPing::timer_ms(BUZZ_LENGTH, stopBuzz);
- lastBuzz = arduinoTime;
- }
- // Query the ultrasonic sensor
- if (nextPulse != 0 && arduinoTime > nextPulse) {
- // Read and filter the sensor data
- unsigned int responseTime = sonar.ping_median(PULSE_SAMPLES);
- // Update pulse count and proceed only if high enough
- if (++pulseCount > PULSE_SKIP) {
- // Report values to the serial port
- Serial.print("Measured ");
- outputDistance(responseTime);
- Serial.print(" (");
- Serial.print(pulseCount);
- Serial.println(")");
- // Update and report record
- if (RECORD_ADDR > -1 && responseTime > recordDistance) {
- recordDistance = responseTime;
- EEPROMWriteInt(RECORD_ADDR, responseTime);
- Serial.print("Wrote new record to ROM: ");
- outputDistance(recordDistance);
- Serial.println();
- }
- // Adjust buzz timing
- boolean solidTone = (buzzDelay == 1);
- if (responseTime == 0) {
- buzzDelay = 0;
- } else {
- if (responseTime <= LOW_DISTANCE) {
- buzzDelay = 1;
- }
- if (responseTime > LOW_DISTANCE && responseTime <= HIGH_DISTANCE) {
- buzzDelay = (responseTime - LOW_DISTANCE) / DISTANCE_RANGE * BUZZ_DELAY_RANGE + MIN_BUZZ_DELAY;
- }
- if (responseTime > HIGH_DISTANCE) {
- buzzDelay = MAX_BUZZ_DELAY;
- }
- }
- if (solidTone && buzzDelay != 1) stopBuzz();
- } else {
- Serial.print("Skipped measurement ");
- Serial.println(pulseCount);
- }
- // Schedule the next pulse
- nextPulse = arduinoTime + PULSE_DELAY;
- }
- }
- // Activate buzzer
- void startBuzz() {
- if (BUZZ_ENABLED) digitalWrite(BUZZ_PIN, HIGH);
- if (STATUS_ENABLED) digitalWrite(STATUS_PIN, HIGH);
- }
- // Stop an ongoing buzz
- void stopBuzz() {
- digitalWrite(BUZZ_PIN, LOW);
- digitalWrite(STATUS_PIN, LOW);
- NewPing::timer_stop();
- }
- // Output response time in human-readable format
- void outputDistance(int responseTime) {
- Serial.print(responseTime);
- Serial.print(' ');
- Serial.write(181); // Micro sign in ISO-8859-1
- Serial.print("s / ");
- Serial.print(sonar.convert_cm(responseTime));
- Serial.print(" cm");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement