Signal Processing Library
in
Library and Tool Development
•
1 year ago
Hi Everyone
Partly as a programming exercise, and partly becouse I believe it would be useful both for myself and others, I have decided to write a signal processing library.
Right now the idea is that you create a SignalPath for each each sensor value you receive.
If there is an incoming value, you assign it to the Path. The signal is then run through all filters specified.
At the end of the loop you close the signal path. No further filtering will occur until there is another incoming value.
A complete signal path, might look something like this:
(assuming all incoming data is stored in data[] and there is some array of SignalPathes, called accFilter
- for (int i = 0; i < data.length; i++) {
- accFilter[i].assign(data[i]);
- }
- for (int i = 0; i < accFilter.length; i++) {
- accFilter[i].offset(250); //i do this, so that the range is in the positive spectrum
- //accFilter[i].highpass(0.08); //i could do this, if I am only interested in motion, rather than position
- accFilter[i].lowpass(0.8); //i do this to smoothen the data readings.
- }
- // do something here, like some fancy visualization
- for (int i = 0; i < accFilter.length; i++) {
- accFilter[i].closePath();
- }
Ideally there should be a second type of filter which can sort of "fill in the blanks" if the incoming data comes at longer time-intervals.
So far all the filters are functions of the SignalProcessing class. However, I guess in order to use a given filter multiple times, these would actually need a class of their own. I will give that a try, but I am a bit fuzzy on how to do that at this moment.
The complete code I have now is here:
- ///////////////////////////////////
- //Signal Processing Class /////////
- ///////////////////////////////////
- class SignalPath
- {
- float inputSignal = 1; //primary input, signal to be processed
- float referenceSignal = 1; //secondary input, used as baseline for detecting events etc. (optional)
- float cleanSignal = 1; //for Lowpassfilter
- float cleanSignalHighpass = 1; //for highpassfilter
- boolean touched = false;
- //constructors
- SignalPath() {
- } // Default constructor: keep default value
- ///////////////////////////////////
- //Generall Methods ////////////////
- ///////////////////////////////////
- //These are generall functions, required to setup your signal chain.
- //A signal chain is started by assigning it an input.
- //By doing sow you also set "touched" to false, allowing the filters to do their work
- void assign(float a) {
- inputSignal = a;
- touched = false;
- }
- //alternative function, if you wish to also assign a baseline
- void assign(float a, float b) {
- inputSignal = a;
- referenceSignal = b;
- touched = false;
- }
- //a signal chain is ended by reading the output.
- //this returns the filtered signal
- //it also prevents any further manipulation of the signal, until a new input is assigned.
- float read() {
- return inputSignal;
- }
- void closePath() {
- touched = true;
- }
- //checks whether your signal has exceeded a specific threshold
- boolean readThreshold(float thresh) {
- if (inputSignal>thresh) {
- return true;
- }
- else {
- return false;
- }
- }
- //prints out some information. Enter a String to Identify the specific debug message
- void debug(String txt) {
- println(txt); //to identify it if there are several
- println("Input Value: " + inputSignal);
- println("Touched: " + touched);
- println("Lowpass Reference: " + cleanSignal);
- println("Highpass Reference: " + cleanSignalHighpass);
- println("Baseline Signal: " + referenceSignal);
- }
- ///////////////////////////////////
- //Acutal Filters ////////////////
- ///////////////////////////////////
- //LowPass Filter
- //use this if your signal is very noisy. This will take out extreme spikes
- //It takes a value between 0 and 1 as parameter (k).
- //If the parameter is 1, the filter is so weak it has no effect
- //If the parameter is 0, the filter has maximum effect, but this is quite useless as well
- //This filter does introduce a slight time delay if the parameter is too high.
- void lowpass(float k)//signal to be processed, and strength of filter
- {
- if (touched == false) {
- float oldSignal = cleanSignal;
- cleanSignal = oldSignal + k * (inputSignal - oldSignal);
- assign(cleanSignal);
- }
- }
- //HighPass Filter
- //The opposite of the LowPass Filter
- //Use this, if for some reason you are interested in the noise in your signal.
- //This also works if you do not care about the actual signal,
- //but are merely interested in the change in signal
- void highpass(float a)//signal to be processed, and strength of filter
- {
- if (touched == false) {
- float oldSignal = cleanSignalHighpass;
- cleanSignalHighpass = oldSignal + a * (inputSignal - oldSignal);
- assign(cleanSignalHighpass - inputSignal);
- }
- }
- //Offset
- //Adds a value to the signal
- void offset(float offsetValue)//signal to be processed, and strength of filter
- {
- if (touched == false) {
- assign(inputSignal + offsetValue);
- }
- }
- }
*
Obviously this is just a start ... this is the first time I have ever written code intended for somebody elses use instead of mine...
I guess I would just like some general feedback:
- Is this useful?
- Does the way I am going about this make sense?
- Any other ways I might implement this?
- Any tips on turning i.e. the lowpass function into an object? Ideally I want the interface to stay as simple as it is now...
- Any algorithms you might want to contribute, or you suggest I look into?
and
- Could somebody point me at a tutorial or something for actually creating a library? to be honest I have no clue on how to actually do that part.
*
Ok, I'll continue playing with this.
Just thought I would lean back and see if I can get some feedback on the way
Cheers
p.