• Generate float values out of pressure sensitive matrix (Arduino)

Hi all,

I am trying to build a pressure sensitive multi-touch pad to use as a kind of keyboard.
For the hardware I build a copper/velostat matrix similar to this one here.
So far I managed to get the pressure value of every row-/column- crossing into PD and sort them. See the patch (screenshot below or link).

My problem is, that I just can't wrap my head around how to calculate a singular float out of the discreet input values of the matrix.

For example: I would like to play and adjust the pitch of a tone by moving my finger along the x-axis of the matrix. So what I need is a float, representing the x-axis location of the peak pressure of my finger.
(Y-axis and pressure values itself will also be needed later on - but i guess one thing after the other...)

I guess the discreet values need to somehow be quantized/merged into one but as I said, I lack the skills of imagining how this needs to be done - be it in PD or written code.

I would be eternally thankful if you could point me into the right direction here.

Thank you already and all the best!
JJ

• Posts 15 | Views 4945
• @jj37592 I think you need to tag the data with the x value so you create a list for each pressure value...... like a midi message, but with the additional y value you want to use later.
x you can add before pressure for each crosspoint with [list prepend x] and y where you wish with [list prepend y] or [list append y]
x will probably be the pitch....... so maybe the midi number.
Then you can filter the list for the maximum pressure.
Remember the order of operations for Pd when applying a filter method.
If your order in the list is x p y then p will drop from [unpack f f f] before x which is perfect.
You will need to pass only the value of x for the highest value of p.
I hope that makes sense.
David.

• @jj37592 Actually it is easier to use \$ than [list prepend] etc.
Anyway, I cannot test but this should work......... base.zip

Every incoming pressure value should be put into [x \$1 y( and then fed to the filter.
x will be fixed for each value (your choice of pitch) and y can be the true value...... so a [pack f f] and a \$2 in the coding message........ [x \$1 \$2(.

The [filter_x] finds the nearest pressure value to 100....... you will have to change that probably.
It does that each time it has received 64 messages........ change the [count 64] to [count 1024] and [== 63] to [== 1023] if there are 1024 messages arriving per data cycle.

Remove the metro stuff as the incoming data will drive the messages.
The highest pressure value will win per cycle.
Set a threshold at the outlet if necessary to cut noise when not playing.

The message x p y can have p scaled and go straight to a midi player.
DO NOT open [text define pressure] while data is arriving......!!! It will crash Pd.
David.

• @whale-av, thank you so much! This is truly amazing!! I must say i'll need some time to understand everything that's going on there (especially didn't know the [text] objects, they don't seem to exist in pd-extended) but i see how this is already solving a lot of problems for midi environments (and probably also for multitouch)!

As i said, I don't grasp everything yet, still i'm asking myself if the following issue is addressed with your patch:
Let's say my finger applies the highest pressure somewhere between column A, B and C. - Could your patch determine the exact location and pressure applied between those 3 columns?

i.e.
crosspoint A1 = 75 pressure
crosspoint B1 = 91 pressure
crosspoint C1 = 83 pressure

Clearly the highest pressure measured is at B1. But also the three values together indicate, that the actual point the highest pressure is applied lies "a bit further" from B1, in the direction of C1.
This is what i think needs to be calculated in order to get a continuous pitch modulation, without steps (midi not 82, 83 etc.)

I hope this gets my point across..? Sorry if you addressed this already, it may well be that I misunderstood something.

Again, thanks a lot and best wishes,
Jakob

• @jj37592 said:

Let's say my finger applies the highest pressure somewhere between column A, B and C. - Could your patch determine the exact location and pressure applied between those 3 columns?

i.e.
crosspoint A1 = 75 pressure
crosspoint B1 = 91 pressure
crosspoint C1 = 83 pressure

Clearly the highest pressure measured is at B1. But also the three values together indicate, that the actual point the highest pressure is applied lies "a bit further" from B1, in the direction of C1.
This is what i think needs to be calculated in order to get a continuous pitch modulation, without steps (midi not 82, 83 etc.)

You will want to keep your calculations "midi" (not stepped) all the way until your oscillator so as to keep all calculations linear. From your example here (3 points) you can measure which point is closest to the peak and how close (You can use the [min] object for this). Equal to peak should bend half a semi tone. And you need to set a threshold for how far apart in pressure they should be for no bend at all (half of peak?).

Something like this maybe? example.pd

• @jj37592 It just returned the highest.
This will return the 3 highest............. and they are then fed into @bocanegra 's example so that the highest pressure has its pitch adjusted........... base3.zip
I think...... but I am in a hurry today and could have made a mistake....

[filter_x] gets the highest pressure.... deletes the line... gets the next highest... deletes.... gets next and then sends a bang on the right outlet to say that it has completed this batch and sent all three.

Something will have to be done to determine whether a pressure is from a higher or a lower pitch though. That could be done within [example]
David.

• @whale-av my example does account for upper or lower pitch, but it assumes that the inputs are already ordered as left neighbour, peak, right neighbour. So a smarter way of doing the presorting would be to identify the one loudest peak, then pair it up with it's two neighbours regardless of their 'loudness' before sending them to [example]

• @bocanegra I agree. My test data is not versatile enough to prove the glide (fixed to just 3 midi notes).
@jj37592 But this should be a working patch......... base4.zip once the metro etc. for testing is removed.
David.

• @whale-av @bocanegra Thank you both so much! I spend the past 5 hours going through your patches trying to understand everything. I think I got what's going on now (seems to work amazingly!!) and will start to install the needed libraries and merge base4.pd and my comport patch. I'll give an update as soon as possible!

• @jj37592 Having slept on it I realised there is an error in [filter_x]
It finds the centre.
Then a value to the side of it (that was after it......because the first one has been deleted).
But the next highest value (to the left) then needs a [text search] again.
I will fix it this evening unless you beat me to it.
David.

• @jj37592 Hmm...... I had to build a new test (because only one copy of each data point will occur in the real patch)...... and I am too tired.
So it drove me mad...... making too many mistakes.
I think it's good.......... base5.zip .... I have seriously checked it.
[example] ignores the lowest left or right value and I thought I had another error that I couldn't find....
It works at [metro 1] on my machine for a 64-bit data set in the test.
David.

• @whale-av thank you very much again for all those efforts. So after fighting around with the needed libraries for [comport] etc. i was able to merge the patches together. The basics seem to work pretty decent, for some reason though the MIDI note value jumps only from X.5 to X.5 or X.49..
So again unfortunately there are steps in the pitch modulation. Couldn't figure out why it happens up to now. Will take a look tomorrow again.

Other than that I was asking myself to which data size I would need to change the filter_x. You wrote before, I would need to change it to 1024 probably. Is that correct?
Also was wondering if my threshold ([pd thres]) is sitting in the right place or if maybe this is causing the problem. See the current patch attached. draft_02.zip and a video below. Again thank you very much. You already helped me a lot!!

• @jj37592 [example] I think ignores left or right side data which is of lower value than the other........ there is no weight given to the lower pressure but that probably will not matter as the pressure point is past the centre in that case.
Anyway, I think this is a solution to any jumpiness........ base6.zip
I have smoothed the output of [example] over 100ms.

I can't imagine you will need 1024 points.
Midi range is 128. At 1cm per note..... which is narrow for a keyboard.... your pressure strip would be 1M28 wide.

I don't think you need a threshold for every pressure point as only the 3 highest pressures make it through [filter_x]
And no message arrives if a threshold is not met which means the counter in [filter_x] will go out of sync. That might not matter at all though.
And you could generate a "done" bang from the output of [sel 13 10] at the top of the matrix.

Anyway, you could just have one threshold at the end after [example] so as to mute if only very low pressure signals arrive and you want to produce no sound..
David.

• sorry for the late reply, somehow the it was not possible to post for some time.

@whale-av, ah, now i understand! So the data size needs to be set to the number of pressure values that i'm sending in to the filter. Makes sense and it seems to work much better now. Still there is indeed a calculation problem in [example] that i now understand. By ignoring the lowest input of the three neightbouring crossings most scenarios cant be handled correctly.
For example:
crossing A / note 61 = pressure 75
crossing B / note 62 = pressure 95
crossing C / note 63 = pressure 76
The highest pressure obviously lies almost exactly at B and in the middle between A and C. The calculated note should be approx. 62.05...
[example] though will calculate that B and C have the smallest difference, leave out A, and output the note 62.2.
So it is indeed needed to calculate all three values together if i want to have the correct peak of pressure. I thought and googled a bit and figured, that it would probably be the best if the three known values are used for a quadratic equation that can help determine a parabola and thus the apex of the pressure applied. I think it will the patch more simple too. Will try to do it with [expr] the next days and give an update as soon as possible.

• hurray, this actually worked. I was able to calculate the parabola and it's maxima out of the three known (highest) values. Here's a screen shot of the parabola abstraction and a video of the main patch at work.
Still a lot of glitching that's fine for now:

Here's a zip too, if somebody is interested: draft_04.zip

I'm working on calculating and implementing the y value too. Probably by using filter and parabola in the same way and feeding the resulting value in at the top of the x value calculation... I hope it works out this way.

Looking ahead: @whale-av, do you have an idea for how to make this work as a multi-touch device? Do you think it's possible to just let the filter throw out several of those peak-lists at once for several touch-events? ...without confusing a moving finger with a 2nd finger moving close to the first one etc. Once again a hint would be really great! Thank you, all the best,
Jakob

Posts 15 | Views 4945
Internal error.

Oops! Looks like something went wrong!