View difference between Paste ID: YGnUeQBU and deMjzCRq
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
}