Skip to content

How to deal with hyperlocality in Savitzky–Golay filtering

xooorx

RIP I'd need to surface solder something on the back of the board and bring that something in front to make it accessible to drive it high when needed

No... you just need to type some C code! The GPIO23 pin is connected to the PS mode pin of the regulator component. If your software makes GPIO23 an output and sets it to 1 then the regulator goes into PWM mode.

(Edit: That TP4 pad on the bottom of the board is also connected to GPIO23, which I think is what's distracting you here, but the "actual" GPIO23 is a pin on the processor not a pad on the board, and you can "drive" it from software).


JayKominek

Taking a look at https://pico-adc.markomo.me/ I'm not sure if switching the power supply mode will have any benefit. I'm also not convinced that is (only) SMPS noise on the signal.

It looks like AVDD could be disconnected from 3V3 and a linear regulator put in place. If I've got any appropriate parts I might give that a go in the next few days. Mostly for the lulz.

As it stands, I don't see any value in the RP2040's increased sample rate; if you need to downsample the 200kS/s signal by a factor of 16-32 in order to get rid of that weird noise, there isn't actually any benefit over collecting clean samples 16-32 times slower.


RIP

JayKominek I'm also not convinced that is (only) SMPS noise on the signal.

Would testing with batteries as I described above answer this question? I (or you) could do this pretty quickly. If you think it's useful, I can prioritize this test, sacrifice a CR2032 (=solder jumpers on it, since at the moment I don't have any suitable battery holder) and do the test in less than 1h late tonight or early tomorrow. You'll have the results tomorrow morning.

JayKominek if you need to downsample the 200kS/s signal by a factor of 16-32 in order to get rid of that weird noise, there isn't actually any benefit over collecting clean samples 16-32 times slower.

Of course. If anything, reducing the number of bits (while keeping the high frequency) might have some value, but the number requested to not "see" the noise might be too low to be useful anyway.

JayKominek As it stands, I don't see any value in the RP2040's increased sample rate;

Sure, if the system has these problems, its use for our purpose is a moot point, and we either need to find root cause and address the problem, or use a different ADC.

But the main question at this point still remain: can we generate all the needed MIDI velocities, without gaps, with a lower sample rate ADC, if we utilize S-G filtering? If so, great! If not, we need higher sample rate, or we'd be designing a subpar system.

xooorx That TP4 pad on the bottom of the board is also connected to GPIO23, which I think is what's distracting you here

You are correct.

xooorx If your software makes GPIO23 an output and sets it to 1 then the regulator goes into PWM mode.

I see, thanks. Then I could run this test easily. I will do it next time I power on the system, perhaps tonight, and report back.


JayKominek

RIP Would testing with batteries as I described above answer this question?

Disconnected from USB, if you connect a battery to the 3V3 net, I think that would work. Without power on Vsys, the switcher's EN pin won't go high, and it won't have any power to work with anyways.

I doubt you ever need to solder to the battery. Just get a decent length of wire exposed and tape the ends to each side of the battery, or compress it a bit.

RIP can we generate all the needed MIDI velocities, without gaps

I've not paid this any attention for a few weeks, because I'm not convinced this is necessary or sufficient for a quality device suitable of expressive performance.

A random number generate can spit out all the MIDI velocities; and a lot of well intentioned signal processing code can end up being fancy random number generators.

The goal probably looks more like "we need to measure pseudovelocities(*) with a dynamic range of 35:1, with about 10 bits of resolution across that range, so that we can maintain at least 7 bits of resolution after going through the velocity-to-MIDI mapping function specified in $paper and rounding to the nearest natural number".

(*): something with a ~linear relationship to real impact velocity.

As your goal stands, I don't know what satisfactory data would even look like.


RIP

JayKominek Disconnected from USB, if you connect a battery to the 3V3 net, I think that would work. Without power on Vsys, the switcher's EN pin won't go high, and it won't have any power to work with anyways.

Mmm, it's not clear to me what you are suggesting. If I power the pico via the battery, the SMPS is engaged anyway. So I was planning to power it via USB normally.

Assuming that the noise is in the analog part of the circuitry (including the ADC), my plan was to power the LEDs and phototransistors via the battery (rather than from the Pico as I am doing now). And use the same voltage for VREF_ADC. This way:

  • the LED illumination should be more constant (even though I doubt they can "flicker" at that frequency)
  • there should not be variation in the phototransistor signal other than what the sensor is doing on its own
  • the ADC should use this more constant reference voltage to compare and to power itself
  • and none of these will have any relationship with the SMPS

JayKominek As your goal stands, I don't know what satisfactory data would even look like.

Lack of that oscillations would be already an improvement, at least on the 8 bit measurements.

JayKominek Del Vento can we generate all the needed MIDI velocities, without gaps

I've not paid this any attention for a few weeks, because I'm not convinced this is necessary or sufficient for a quality device suitable of expressive performance.

It's definitely not sufficient. It might not even be necessary, but still worth investigating no?

JayKominek The goal probably looks more like "we need to measure pseudovelocities(*) with a dynamic range of 35:1, with about 10 bits of resolution across that range, so that we can maintain at least 7 bits of resolution after going through the velocity-to-MIDI mapping function specified in $paper and rounding to the nearest natural number".

Exactly! State as a question with different words (namely "is that possible with sampling frequency nnn kHz?") is what I am asking. And my back of the envelope math above answers half of that question with "no, that requires higher frequency sampling with the comparator approach". So I'm trying to find an answer to the other half, i.e. "what about the S-G approach?"


JayKominek

RIP Mmm, it's not clear to me what you are suggesting. If I power the pico via the battery, the SMPS is engaged anyway. So I was planning to power it via USB normally.

All assuming your battery is a reasonable voltage to power the RP2040 directly:

If you apply power to 3V3 (pin 36 of the Pico), that will be injected after the switching supply. The USB +5V comes in on VBUS, passes through D1 into VSYS and then the regulator's input.

Voltage might flow backwards through the regulator. Not sure. If it does (check with a meter?), grounding out 3V3_EN should help ensure it doesn't turn on and start doing things. Doing that might let you run off a battery, and be connected to USB, now that I think about it.

RIP Assuming that the noise is in the analog part of the circuitry (including the ADC), my plan was to power the LEDs and phototransistors via the battery (rather than from the Pico as I am doing now)

Won't hurt.

RIP And use the same voltage for VREF_ADC.

VREF is separated from 3V3 by a 200 ohm resistor. I wouldn't expect the battery to prevent noise on VREF unless R7 was removed.

Has somebody tried this that you're aware of? It just doesn't seem productive. But a coin cell will be safe, at least.


RIP

Ok, sooooo…..

JayKominek All assuming your battery is a reasonable voltage to power the RP2040 directly:

I tried with a new CR2032 which was a 3.38V before the test. During the test its voltage dropped to 1.7V and the pico won't power up. After the test the battery raised back to around 2.9V. I guess the whole thing needs more ampere than the battery can supply (and that was before I attached the SD card, whose SPI must consume some more). I guess I should have done some math before, but I didn't 😅 -- I thought to try with two D-cells in series, but I did not have any around that had enough juice to reach more than 3V together. So I tried with (another) new CR2032 connected as I described earlier.

JayKominek VREF is separated from 3V3 by a 200 ohm resistor. I wouldn't expect the battery to prevent noise on VREF unless R7 was removed.

Makes sense. Perhaps it can mitigate such noise a bit, otherwise I am not sure what they mean in the datasheet about that then. In any case, I tried it that way, since that was the only thing I could do (when you only have a hammer…..) -- For the tests below when I say "battery" I mean putting the battery between ADC_VREF and ground, and using it to power LEDs and phototransistors. Everything else is always powered with USB.

JayKominek Has somebody tried this that you're aware of?

Not that I know of.

For reference, here is what a strike looks with USB power. You've seen this already:

And here is what a strike looks like with USB power and PWM forced on like @xooorx suggested (gpio_pull_up(23);)

And this is with battery (and still forced PWM):

Now, you have certainly seen that the noise is shrinking. Here is a zoom in of the noise with the default USB power:

Pay attention to the vertical scale which is different among these plots. The horizontal scale is instead more or less the same. This is with PWM power -- marginally beter

And finally, here is a zoom for the battery.

Do notice that with the battery the noise is indeed much better, but not as good as it seems at first sight, since the whole signal is somewhat less (compare how the peak does not reach the yellow line in the strike plot), hence the S/N ratio needs to take the smaller signal into account. Yet, it's definitely better, since it's just about 10 ADC values of noise for about 4096-1800 = ~1300 ADC values of signal,

Whereas for the regular / PWM powered cases the signal signal is 4096 - 2400 = ~1600 ADC values and the noise between 30 and 40 ADC values: much more noise for only a bit more signal.

That D-cell tests seems appropriate…. It would be nice to have the code self-sufficient (rather than dependent on the computer issuing commands via minicom as it is now) so one does not need to attach the USB as it is now in my test setup: https://github.com/davidedelvento/no-OS-FatFS-SD-SPI-RPi-Pico

I don't think I'll have the time to do it this weekend.


RIP

RIP I don't think I'll have the time to do it this weekend.

If any of you does the test, please let me know (you'll need a suitable SD card and some way to attach it to the Pico, as described at https://github.com/davidedelvento/no-OS-FatFS-SD-SPI-RPi-Pico ).

If you only want to play with the data, you can download it here, it is 6MB, in the same format as described at https://github.com/davidedelvento/Mybrid/tree/main/data/RPiPico%2BEAITRCA6 (note that it is in binary, not MIDI, format, unlike I did earlier).


JayKominek

RIP Do notice that with the battery the noise is indeed much better, but not as good as it seems at first sight, since the whole signal is somewhat less

With the battery on there, probably acting as a large strange capacitor, the structure of the noise is greatly reduced. That starts looking like something you can apply filtering to usefully.

Probably the signal is smaller because your battery's voltage has been pulled down by… whatever weirdness is happening. So the LED is emitting less, and Vce on the phototransistor is lower, so Ice is reduced for a given amount of light hitting it. Vref dropping because it is also connected to the battery won't account for all of that.

I'd take it as a good sign.

RIP That D-cell tests seems appropriate….

Hmm, not sure if that will be better or worse. I thought they had quite high ESR, but when I went looking for information, (1) I couldn't find it and (2) what I did find suggested it was quite a bit lower than I thought. So I look forward to hearing what happens.


RIP

Wow! The battery did it.

As you anticipated the ESR was a bit of a problem (voltage dropped to 3.05V during the test) but I was able to complete the ADC capture without attaching a computer (and thus without knowing much if it was running correctly until after the fact). Yet, look how clean it is!!

Here is a detail:

Not sure about that residual 160Hz modulation, it might be the Pico itself or it may be some external signal. Possibly even light? The setup was a bit too precarious to perform in darkness, so I had the lights on (all LEDs, as matter of fact). Pointed as far away from the hammer area as I could, but still not in darkness.

I will post the data to https://github.com/davidedelvento/Mybrid/tree/main/data/RPiPico%2BEAITRCA6 in a few moments, but I had to let you know ASAP 😃


JayKominek

RIP Not sure about that residual 160Hz modulation, it might be the Pico itself or it may be some external signal. Possibly even light?

Yeah that's a pretty odd bit of noise. One would expect 30, 60, or 120Hz noise from lights or other AC sources in one's home.

Going wildly out on a limb, do you maybe write to the SD card at some multiple of 160Hz? Or maybe accumulate some power-of-two worth of writes to the card every 160Hz? I think most flash devices do weird buffering under the hood. 250kS/s, 1/160th of a second, 1562 samples. If you, hypothetically packed the two 12 bit samples into 3 bytes, that'd be 4686 bytes, a bit more than a 4k page.


RIP

JayKominek Yeah that's a pretty odd bit of noise. One would expect 30, 60, or 120Hz noise from lights or other AC sources in one's home.

Yes! The only reason I mentioned AC lights is that I eyeballed the frequency, so it could have been 120Hz if I did it mental math wrong.

JayKominek Going wildly out on a limb, do you maybe write to the SD card at some multiple of 160Hz?

Not explicitly. The SD-card-writing is done via SPI by a library which I just peeked a bit under the hood, but I did not examine it very closely. I know that it does use IRQs.

I wanted to use IRQ for the ADC, but instead I am just sampling as fast as I can in a loop, so no particular frequency of mine (but the SPI has its own, which I set but is not fully honored: it goes somewhat slower)

JayKominek If you, hypothetically packed the two 12 bit samples into 3 bytes

That's almost what I do: 2 samples and 12 bit of elapsed time (with overflow, which I then unroll while doing data analysis). As linked in the README of the linked repo, the code for this 3-byte stuff is here and in the same repo is the library in use.

At this point I consider myself satisfied, and I'll go back to the MIDI velocity estimation based on this cleaner data. In that regard, I think that your own discussion here and @xooorx 's colevity here are already (close to) the back-of-the-envelope SG that I was asking.

In other words: if the scanning frequency is (say) a fast but comfortable 10kHz, i.e. the interval between samples is 0.1ms, then at fff the hammers move less than 1mm between samples. If we can measure the hammer position with enough spatial resolution (say 1% just to make that ballpark of 1 MIDI velocity out of a value of about 100 -- yes I know that logarithmically it will be a bit less) then we are ok in term of resolution. Eyeballing your distance-to-ADC plot, if one ignores that "dip" at close distances (which is horrible for this purpose), it feels like we do have the resolution.

The question remains that I am not sure SG will behave correctly for such a MIDI velocity computation at the upper end of the dynamics, with the approach of simply accumulating and utilizing the last ~ 23 values (as your code was doing last time I looked). If that fff speed was constant, 23 values would be about 23mm and that is about half the travel of the hammer. Obviously the speed is far from constant if such a long range, so the distance will be much less -- but the important part will be the last couple of samples only. Would a fixed-window SG filter with 23 values work as we want in these conditions? I am still not sure, but at least that's progress compared to my understanding of last week. I'll think more about it, and hopefully @xooorx and/or @luns will chime in with additional insights (and of course you, Jay, might have ones too).


« Previous Page