From 53ffa5d85bee370d69591e558100f1918cf08c1d Mon Sep 17 00:00:00 2001 From: Thomas Friedrichsmeier Date: Wed, 5 Apr 2023 21:43:08 +0200 Subject: [PATCH 1/4] Allow setting list of pins to sample after construction Arguably, in user code, the list of pins to sample will typically be known and fixed at compile-time. However, when wrapping this into a library (Mozzi; for the purpose of providing a cross-platform analog read mechanism), it will be very helpful to have a way to adjust the pins to sample after construction. --- src/AdvancedADC.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 647250b..46321d1 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -42,10 +42,18 @@ class AdvancedADC { adc_pins[n_channels++] = analogPinToPinName(p); } } + AdvancedADC(): n_channels(0), descr(nullptr) {} ~AdvancedADC(); bool available(); SampleBuffer read(); int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); + int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, size_t n_pins, pin_size_t *pins) { + static_assert(n_pins < AN_MAX_ADC_CHANNELS, "A maximum of 5 channels can be sampled successively."); + for (size_t i = 0; i < n_pins; ++i) { + adc_pins[i] = analogPinToPinName(pins[i]); + } + n_channels = n_pins; + } int stop(); }; From 04f127541f158381d63418c35be36b92c5d34e1e Mon Sep 17 00:00:00 2001 From: Thomas Friedrichsmeier Date: Wed, 5 Apr 2023 21:50:52 +0200 Subject: [PATCH 2/4] Enforce limit at runtime rather than static assertion --- src/AdvancedADC.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 46321d1..3754bf1 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -48,7 +48,7 @@ class AdvancedADC { SampleBuffer read(); int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, size_t n_pins, pin_size_t *pins) { - static_assert(n_pins < AN_MAX_ADC_CHANNELS, "A maximum of 5 channels can be sampled successively."); + if (n_pins > AN_MAX_ADC_CHANNELS) n_pins = AN_MAX_ADC_CHANNELS; for (size_t i = 0; i < n_pins; ++i) { adc_pins[i] = analogPinToPinName(pins[i]); } From 82ae24a2a9b46e92b58b212c72abb0127644ee17 Mon Sep 17 00:00:00 2001 From: Thomas Friedrichsmeier Date: Wed, 5 Apr 2023 22:20:05 +0200 Subject: [PATCH 3/4] Add missing bit I shall test my PR before submitting... --- src/AdvancedADC.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 3754bf1..844985b 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -53,6 +53,7 @@ class AdvancedADC { adc_pins[i] = analogPinToPinName(pins[i]); } n_channels = n_pins; + return begin(resolution, sample_rate, n_samples, n_buffers); } int stop(); }; From 4c365697fd74d2220439ad40bb84a61baa181f77 Mon Sep 17 00:00:00 2001 From: Thomas Friedrichsmeier Date: Wed, 12 Apr 2023 14:14:12 +0200 Subject: [PATCH 4/4] Add usage example for dynamic ADC multi channel setup --- .../ADC_Multi_Channel_Dynamic.ino | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 examples/Advanced/ADC_Multi_Channel_Dynamic/ADC_Multi_Channel_Dynamic.ino diff --git a/examples/Advanced/ADC_Multi_Channel_Dynamic/ADC_Multi_Channel_Dynamic.ino b/examples/Advanced/ADC_Multi_Channel_Dynamic/ADC_Multi_Channel_Dynamic.ino new file mode 100644 index 0000000..c208289 --- /dev/null +++ b/examples/Advanced/ADC_Multi_Channel_Dynamic/ADC_Multi_Channel_Dynamic.ino @@ -0,0 +1,74 @@ +/* ADC Multi Channel sampling usage demo + * + * Queries for pin numbers to sample on the Serial Monitor, then records and prints three readings on + * each of those pins at a leisurely rate of 2 Hz. + */ + +#include + +AdvancedADC adc; +uint64_t last_millis = 0; +pin_size_t active_pins[AN_MAX_ADC_CHANNELS]; +int num_active_pins = 0; +const int samples_per_round = 3; + +void queryPins() { + Serial.println("Enter pins to sample (number only, e.g. 3,4 for A3, and A4). Enter to repeat previous round."); + + int old_num_active_pins = num_active_pins; + num_active_pins = 0; + String buf; + int c; + do { + c = Serial.read(); + if (c < 0) continue; + + if (c == ',' || c == '\n') { + buf.trim(); + if (buf.length()) { + active_pins[num_active_pins++] = buf.toInt() + A0; + buf = String(); + } + } else { + buf += (char) c; + } + } while (!(c == '\n' || num_active_pins >= AN_MAX_ADC_CHANNELS)); + + // No (valid) input? Repeat previous measurement cylce + if (!num_active_pins) { + num_active_pins = old_num_active_pins; + } +} + +void setup() { + Serial.begin(9600); + while (!Serial) {}; +} + +void loop() { + queryPins(); + if (num_active_pins) { + // Resolution, sample rate, number of samples per buffer per channel, queue depth, number of pins, array of pins. + if (!adc.begin(AN_RESOLUTION_16, 2, 1, samples_per_round, num_active_pins, active_pins)) { + Serial.println("Failed to start analog acquisition!"); + while (1); + } + + for (int i = 0; i < samples_per_round; ++i) { + while(!adc.available()) {}; // Your code could do something useful while waiting! + + SampleBuffer buf = adc.read(); + + for (int i = 0; i < num_active_pins; ++i) { + Serial.print(buf[i]); + Serial.print(" "); + } + Serial.println(); + + // Release the buffer to return it to the pool. + buf.release(); + } + + adc.stop(); + } +}