diff --git a/ArduinoMetalDetector.ino b/ArduinoMetalDetector.ino index 2a33d34..8ca94b0 100644 --- a/ArduinoMetalDetector.ino +++ b/ArduinoMetalDetector.ino @@ -22,102 +22,103 @@ * along with this program. If not, see . */ -// Number of cycles from external counter needed to generate a signal event -#define CYCLES_PER_SIGNAL 5000 - -// Base tone frequency (speaker) -#define BASE_TONE_FREQUENCY 280 - -// Frequency delta threshold for fancy spinner to trigger -#define SPINNER_THRESHOLD 700 - -// Pin definitions -#define SENSITIVITY_POT_APIN 1 -#define SPEAKER_PIN 2 -#define SPINNER_PIN 9 -#define TRIGGER_BTN_PIN 11 -#define RESET_BTN_PIN 12 - -unsigned long lastSignalTime = 0; -unsigned long signalTimeDelta = 0; - -boolean firstSignal = true; -unsigned long storedTimeDelta = 0; - -// This signal is called whenever OCR1A reaches 0 -// (Note: OCR1A is decremented on every external clock cycle) -SIGNAL(TIMER1_COMPA_vect) -{ - unsigned long currentTime = micros(); - signalTimeDelta = currentTime - lastSignalTime; - lastSignalTime = currentTime; - - if (firstSignal) - { - firstSignal = false; - } - else if (storedTimeDelta == 0) - { - storedTimeDelta = signalTimeDelta; - } - - // Reset OCR1A - OCR1A += CYCLES_PER_SIGNAL; -} - -void setup() -{ - // Set WGM(Waveform Generation Mode) to 0 (Normal) - TCCR1A = 0b00000000; - - // Set CSS(Clock Speed Selection) to 0b111 (External clock source on T0 pin - // (ie, pin 5 on UNO). Clock on rising edge.) - TCCR1B = 0b00000111; - - // Enable timer compare interrupt A (ie, SIGNAL(TIMER1_COMPA_VECT)) - TIMSK1 |= (1 << OCIE1A); - - // Set OCR1A (timer A counter) to 1 to trigger interrupt on next cycle - OCR1A = 1; - - pinMode(SPEAKER_PIN, OUTPUT); - pinMode(SPINNER_PIN, OUTPUT); - pinMode(TRIGGER_BTN_PIN, INPUT_PULLUP); - pinMode(RESET_BTN_PIN, INPUT_PULLUP); -} - -void loop() -{ - if (digitalRead(TRIGGER_BTN_PIN) == LOW) - { - float sensitivity = mapFloat(analogRead(SENSITIVITY_POT_APIN), 0, 1023, 0.5, 10.0); - int storedTimeDeltaDifference = (storedTimeDelta - signalTimeDelta) * sensitivity; - tone(SPEAKER_PIN, BASE_TONE_FREQUENCY + storedTimeDeltaDifference); - - if (storedTimeDeltaDifference > SPINNER_THRESHOLD) - { - digitalWrite(SPINNER_PIN, HIGH); - } - else - { - digitalWrite(SPINNER_PIN, LOW); - } - } - else - { - noTone(SPEAKER_PIN); - digitalWrite(SPINNER_PIN, LOW); - } - - if (digitalRead(RESET_BTN_PIN) == LOW) - { - storedTimeDelta = 0; - } -} - -float mapFloat(int input, int inMin, int inMax, float outMin, float outMax) -{ - float scale = (float)(input - inMin) / (inMax - inMin); - return ((outMax - outMin) * scale) + outMin; -} +// Number of cycles from external counter needed to generate a signal event +// Larger number: Better resolution and longer aquisition time. Max value 65535 (16 bit) +#define CYCLES_PER_SIGNAL 5000 +// Base tone frequency (speaker) +#define BASE_TONE_FREQUENCY 280 + +// Frequency delta threshold for fancy spinner to trigger +#define SPINNER_THRESHOLD 700 + +// Pin definitions +#define SENSITIVITY_POT_APIN 1 +#define SPEAKER_PIN 2 +#define SPINNER_PIN 9 +#define TRIGGER_BTN_PIN 11 +#define RESET_BTN_PIN 12 + +unsigned long lastSignalTime = 0; +long signalTimeDelta = 0; +long storedTimeDelta = 0; + +// This signal is called when the timer value TCNT1 reaches OCR1A +// (Note: TCNT1 is incremented on every external clock cycle) +SIGNAL(TIMER1_COMPA_vect) +{ + unsigned long currentTime = micros(); + signalTimeDelta = currentTime - lastSignalTime; + lastSignalTime = currentTime; + + if (storedTimeDelta == 0) + { + storedTimeDelta = signalTimeDelta; + } + + // Move OCR1A value ahead + OCR1A += CYCLES_PER_SIGNAL; +} + +void setup() +{ + // Set WGM(Waveform Generation Mode) to 0 (Normal) + // Timer runs from 0x00 to 0xFFFF and overruns + TCCR1A = 0b00000000; + + // Set CSS(Clock Speed Selection) to 0b111 (External clock source on T0 pin + // (ie, pin 5 on UNO). Clock on rising edge.) + TCCR1B = 0b00000111; + + // Reset counter and start measuring time + TCNT1 = 0; + OCR1A = CYCLES_PER_SIGNAL; + lastSignalTime = micros(); + + // Clear interrupt flag by setting OCF1A high + TIFR1 |= (1 << OCF1A); + + // Enable timer compare interrupt A (ie, SIGNAL(TIMER1_COMPA_VECT)) + TIMSK1 |= (1 << OCIE1A); + + pinMode(SPEAKER_PIN, OUTPUT); + pinMode(SPINNER_PIN, OUTPUT); + pinMode(TRIGGER_BTN_PIN, INPUT_PULLUP); + pinMode(RESET_BTN_PIN, INPUT_PULLUP); +} + +void loop() +{ + if (digitalRead(TRIGGER_BTN_PIN) == LOW) + { + float sensitivity = mapFloat(analogRead(SENSITIVITY_POT_APIN), 0, 1023, 0.5, 10.0); + int storedTimeDeltaDifference = storedTimeDelta - signalTimeDelta; + unsigned int toneFrequency = BASE_TONE_FREQUENCY + abs(storedTimeDeltaDifference) * sensitivity; + tone(SPEAKER_PIN, toneFrequency); + + if (storedTimeDeltaDifference > SPINNER_THRESHOLD) + { + digitalWrite(SPINNER_PIN, HIGH); + } + else + { + digitalWrite(SPINNER_PIN, LOW); + } + } + else + { + noTone(SPEAKER_PIN); + digitalWrite(SPINNER_PIN, LOW); + } + + if (digitalRead(RESET_BTN_PIN) == LOW) + { + storedTimeDelta = 0; + } +} + +float mapFloat(int input, int inMin, int inMax, float outMin, float outMax) +{ + float scale = (float)(input - inMin) / (inMax - inMin); + return ((outMax - outMin) * scale) + outMin; +}