-
Notifications
You must be signed in to change notification settings - Fork 0
/
piezoTrigger.cpp
120 lines (98 loc) · 2.65 KB
/
piezoTrigger.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
////////////////////////////
///
/// piezoTrigger class
///
/// Watch an analog input
/// Calculate velocity value based on 3 samples
///
/// (y3 + y2 + y1) / 3 + (y3 - y1) / 2
///
/// Call a callback function when a threshold is passed
/// Max velocity on callback is 127, like with midi velocity
///
///
///
////////////////////////////
#include <cstdint>
#include <Arduino.h>
#include <elapsedMillis.h>
#include <ADC.h>
#include "piezoTrigger.h"
#undef dbg
#define dbg( ... ) {}
#if defined(__MKL26Z64__)
#define ANALOG_DEFAULT_REFERENCE 3300
#endif
ADC adc;
inline uint32_t piezoTrigger::get_sample()
{
return adc.adc0->analogRead(piezoInput) * 1000.0f *
(ANALOG_DEFAULT_REFERENCE / 1000.0) / 4095.0f;
}
void piezoTrigger::setup()
{
// Set up builtin adc for piezo input
pinMode( piezoInput, INPUT_DISABLE );
adc.adc0->setResolution( 12 );
adc.adc0->setConversionSpeed( ADC_CONVERSION_SPEED::HIGH_SPEED );
adc.adc0->setSamplingSpeed( ADC_SAMPLING_SPEED::MED_SPEED );
dbg("piezoTrigger on pin %lu\n", piezoInput);
}
void piezoTrigger::loop()
{
static uint32_t sample_count = 0;
uint32_t t_mv;
t_mv = get_sample();
////
// Experiments to find a way to get a velocity mapped to the
// incoming piezo signal. Looks like the first 3 samples
// above a threshold at 1 msec intervals will be a good estimate.
// Slope based on 3 samples = avg( slope1, slope 2 )
//
// (y2 - y1) + (y3 - y2) / 2 = (y3 - y1) / 2
//
// It might be useful to add the mean value as a factor...
//
// (y3 + y2 + y1) / 3 + (y3 - y1) / 2
//
////
if ((t_mv > threshhold_mv) && !fired) {
[[maybe_unused]] uint32_t time_microsec = micros();
if (sample_count < NUM_SAMPLES) {
// dbg( "sample = %5lu\n", t_mv );
samples[sample_count++] = t_mv;
}
for (; sample_count < NUM_SAMPLES; sample_count++) {
delayMicroseconds(200);
samples[sample_count] = get_sample();
dbg( "sample = %5lu, %5lu\n", get_sample(), micros() - time_microsec );
}
if (sample_count == NUM_SAMPLES) {
uint32_t trig = 0;
for (unsigned i = 0; i < NUM_SAMPLES; i++)
trig += samples[i];
trig /= NUM_SAMPLES;
uint32_t slope = (samples[NUM_SAMPLES - 1] > samples[0]?
samples[NUM_SAMPLES - 1] - samples[0] : 0) / 2;
trig += slope;
uint32_t vel = (trig * 127) / 3300;
if (vel > 127)
vel = 127;
dbg( "trig = %5lu, %5lu usec\n", vel, micros() - time_microsec );
func( vel );
fired = true;
trigger_time = 0;
}
}
else if ((t_mv < threshhold_mv) && (trigger_time > holdoff_msec)) {
fired = false;
sample_count = 0;
}
if (testing) {
if (test_time > 1000) {
dbg( "t_mv = %5lu\n", t_mv);
test_time = 0;
sample_count = NUM_SAMPLES + 1;
}
}
}