From 0d26d7ce777c3ee5b2f5b875effb05d6b1692fbb Mon Sep 17 00:00:00 2001 From: szihlmann <86130954+szihlmann@users.noreply.github.com> Date: Sat, 18 Dec 2021 00:33:58 +0100 Subject: [PATCH 1/4] Forked and resolved mixed line endings --- ArduinoMetalDetector.ino | 195 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/ArduinoMetalDetector.ino b/ArduinoMetalDetector.ino index 2a33d34..b85839b 100644 --- a/ArduinoMetalDetector.ino +++ b/ArduinoMetalDetector.ino @@ -22,102 +22,101 @@ * 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 +#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; +} From 0ec99af3f002f5996ee67d62b4c87e2acd579036 Mon Sep 17 00:00:00 2001 From: szihlmann <86130954+szihlmann@users.noreply.github.com> Date: Sat, 18 Dec 2021 00:38:53 +0100 Subject: [PATCH 2/4] Allow negative differences of Time-Deltas Allow negative differences of (storedTimeDelta - signalTimeDelta) by using a long datatype and using abs() of the difference. This accounts for metals that decrease the colpitts oscillator frequency. --- ArduinoMetalDetector.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ArduinoMetalDetector.ino b/ArduinoMetalDetector.ino index b85839b..7c0c582 100644 --- a/ArduinoMetalDetector.ino +++ b/ArduinoMetalDetector.ino @@ -39,10 +39,10 @@ #define RESET_BTN_PIN 12 unsigned long lastSignalTime = 0; -unsigned long signalTimeDelta = 0; +long signalTimeDelta = 0; boolean firstSignal = true; -unsigned long storedTimeDelta = 0; +long storedTimeDelta = 0; // This signal is called whenever OCR1A reaches 0 // (Note: OCR1A is decremented on every external clock cycle) @@ -91,8 +91,9 @@ 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); + int storedTimeDeltaDifference = storedTimeDelta - signalTimeDelta; + unsigned int toneFrequency = BASE_TONE_FREQUENCY + abs(storedTimeDeltaDifference) * sensitivity; + tone(SPEAKER_PIN, toneFrequency); if (storedTimeDeltaDifference > SPINNER_THRESHOLD) { From 5781440242be5ce136665a12dd2ffce971639595 Mon Sep 17 00:00:00 2001 From: szihlmann <86130954+szihlmann@users.noreply.github.com> Date: Sat, 18 Dec 2021 20:29:58 +0100 Subject: [PATCH 3/4] Clarified TCNT1 vs OCR1A Clarified that TCNT1 is the counter variable. OCR1A is the register TCNT1 will be compared to. TCNT1 is increasing NOT decreasing. --- ArduinoMetalDetector.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ArduinoMetalDetector.ino b/ArduinoMetalDetector.ino index 7c0c582..bf8f04c 100644 --- a/ArduinoMetalDetector.ino +++ b/ArduinoMetalDetector.ino @@ -44,8 +44,8 @@ long signalTimeDelta = 0; boolean firstSignal = true; long storedTimeDelta = 0; -// This signal is called whenever OCR1A reaches 0 -// (Note: OCR1A is decremented on every external clock cycle) +// 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(); @@ -61,7 +61,7 @@ SIGNAL(TIMER1_COMPA_vect) storedTimeDelta = signalTimeDelta; } - // Reset OCR1A + // Move OCR1A value ahead OCR1A += CYCLES_PER_SIGNAL; } From 40c70bb1cd856a604a1dfb22475af851e37d3a94 Mon Sep 17 00:00:00 2001 From: szihlmann <86130954+szihlmann@users.noreply.github.com> Date: Sun, 19 Dec 2021 00:01:04 +0100 Subject: [PATCH 4/4] Fixed Timer 1 initialisation issue TIMER1_COMPA_vect was executed immediately after enabling timer compare interrupt A since the interrupt flag was not cleared. Because the OCR1A value was set to 1 AFTER enabling compare interrupt, wrong values for storedTimeDelta were obtained during Arduino startup. --- ArduinoMetalDetector.ino | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ArduinoMetalDetector.ino b/ArduinoMetalDetector.ino index bf8f04c..8ca94b0 100644 --- a/ArduinoMetalDetector.ino +++ b/ArduinoMetalDetector.ino @@ -23,6 +23,7 @@ */ // 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) @@ -40,8 +41,6 @@ unsigned long lastSignalTime = 0; long signalTimeDelta = 0; - -boolean firstSignal = true; long storedTimeDelta = 0; // This signal is called when the timer value TCNT1 reaches OCR1A @@ -52,11 +51,7 @@ SIGNAL(TIMER1_COMPA_vect) signalTimeDelta = currentTime - lastSignalTime; lastSignalTime = currentTime; - if (firstSignal) - { - firstSignal = false; - } - else if (storedTimeDelta == 0) + if (storedTimeDelta == 0) { storedTimeDelta = signalTimeDelta; } @@ -68,18 +63,24 @@ SIGNAL(TIMER1_COMPA_vect) 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); - // 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);