Perversely, you're doing the opposite of what you want, mathematically. You're differentiating the signal (i.e. dv/dt). You want to know when the signal is plateaued, and mathematically this is when dv/dt = 0.
Haha, I feel dumb, I totally didn't think of it that way.
Is the signal periodic ?
Yes. Although, not regularly periodic. There could be anywhere between a few milliseconds and several seconds between steps. But there should always be a period between steps, even if it is short. The smallest expected step level should be about 50mV, but usually more than that, about 200+mV.
If it is then using your d/dT interrupt makes life
easy. Have the ADC run continuously and take the prior sample when
the d/dT occurs. That sample is the final decay level just prior to next
step.
Hmm, yes, that would be a better approach. The signal has a rounded 'shoulder' just before it plateaus, so I guess if I took the reading at the point of interrupt, I would probably catch the shoulder, and not the final plateau level. Using your approach would be more accurate.
I'm assuming, from the implications of the original post, that this is a stair-step kind of waveform.
Yes, precisely.
Going back to what Cerebus said in his first post, I was thinking about it in the shower last night (where all the good ideas are born, right?
), and had an idea about how to implement that approach just in software, and in a very easy way at that.
I can set up the ADC to sample at a fixed frequency - say, 1kHz. Then I can use a simple 8-bit integer (or maybe 16 if I need more) as a simple historical buffer that indicates whether the last 8 readings were higher/lower than the previous - where a 1 bit is higher/lower, and a zero bit is unchanged. I would probably want to use a certain margin when making the higher/lower comparison, to account for noise. Then, all I have to do is look at whether the integer value of the buffer variable is equal to zero, and when it is, I have a plateaued signal, and I can take the last ADC reading as my level.
Something like the following pseudocode:
left-shift buffer by one
if (current_reading > last_reading + margin) or (current_reading < last_reading - margin) then
buffer = buffer | 0x1
last_reading = current_reading
if buffer == 0 then
<do whatever with current reading>
Does this sound good?
And, if I need more than 8 history buffer bits, then I could use a 16-bit integer either fully or with a mask (for, say, 10 bits). ADC sampling rate could also be adjusted to ensure I get a buffer's worth of samples in the minimum expected period between steps.
I'm sure I once saw something vaguely similar (at least, the concept of using an integer variable as a buffer of binary flags), but used for software de-bouncing of button inputs, but I don't recall where I saw it.
Oh, and finally, one question about the circuit in my original post: would it be best to put a diode (a schottky?) to ground between the AC coupling cap and the input to the op-amp? So as to prevent negative pulses (from downward steps in the input signal) going to the op-amp. I might just breadboard it for kicks to find out how it behaves in the real world.