Help with signal conditioning

robtillaart:
Yes, please post the code, you want to share, I'll comment (maybe others too :wink:

Here it is (I wanted to triple check it and test it before posting):

/*  Breath Sensor and Moving average
    By Luca Brigatti
    Adapted from an algorithm by robtillaart
    Calculates the derivative (difference) between two subsequent sensor readings
    and calculates a moving average of the derivative signal
    Optimized for a running average of 2^n elements ( 2, 4, 8 , 16 etc.)
    Sensor used for testing is breath sensor by Modern Devices: 
    http://shop.moderndevice.com/products/wind-sensor
    
*/

const boolean DEBUG = true ;  // true, to print data on the serial port. false to do something else
const int MAVSIZE = 16 ; // Elements (size) of the moving average

// Signal variables
int oldval ;
int newval ;
int derivative ;  // will hold oldval - newval

// Moving Average variables
int MavValues [MAVSIZE] ;  // Holds the last MAVSIZE values of the moving average
int mavtot = 0 ; // total of the moving average (before the division)
int mav = 0 ; // Moving average = mavtot / MAVSIZE
int mavindex = 0 ; // next value to use for the moving average
int sizemask ; // Mask to use for the index counter


void setup()  {

  Serial.begin(9600);  // <--- Low speed: easier to collect data from the serial port, High Speed: smoother curve and tighter moving average
  sizemask = MAVSIZE -1 ;  // If MAVSIZE is B10000 (16), sizemask is B01111 (15)
  setupmav  (MAVSIZE) ; // Initialize the Moving Average with the first MAVSIZE values
  if (DEBUG) Serial.println("Square breathing 0.1");

}

void loop()  {

  newval = analogRead(A2);  // measure the wind
  derivative = (newval - oldval);  // first derivative of the signal
  updatemav (MAVSIZE) ;  // Updates the moving average, a new mav value is assigned.
  
  if (DEBUG) serialdump() ;
  else ; // Do something with mav , the moving average of the derivative or newval, the actual reading
  
  oldval = newval ; // Remember previous value for next derivative

}

void serialdump () {

  // OUTPUT CAN BE COPIED TO EXCEL
  // Put here what you want to print
  Serial.print(millis());
  Serial.print(";");
  Serial.print(oldval);
  Serial.print(";");
  Serial.print(newval);
  Serial.print(";");
  Serial.print(derivative);
  Serial.print(";");
  Serial.print(mav);
  Serial.print(";");

  // SQUARE OUTPUT (% as example)
  if (derivative > 0 && newval > 40) Serial.println(100);
  else Serial.println(0);

}

void setupmav(int mavsize) {

  mav = 0 ;
  mavtot = 0 ;
  oldval = analogRead(A2) ;  // Starting point, change with Pin actually used
  
  for (int i = 0 ; i < mavsize; i++ ) {

    newval = analogRead(A2);  // measure the wind, change with pin used
    derivative = (newval - oldval);  // first derivative of the signal
    MavValues [i] = derivative ;  // Remember this value
    mavtot +=  derivative;  // Update the running total
    oldval = newval ; // New Value is now old value

  }

 mav = mavtot / mavsize ; // First moving average

}

void updatemav (int mavsize) {

  mavtot += derivative ;  // Add latest value
  mavtot -= MavValues [mavindex] ;  // Subtract oldest value in the array
  MavValues [mavindex] = derivative ;  // Newest value in array, replaces oldest value
  mav = mavtot / mavsize ; // New moving average
  mavindex++ ; // Point to the next element in the array, now the oldest element.
  mavindex &= sizemask ; // Circle back to 0 if reached size of the moving average  (e.g.  10000 & 01111 (16 & 15) = 00000 (0)  )

}

My algorithm is not as abstracted and nearly as useful as your library but it is optimized for a situation like the one at hand:
Putting the initial loading of the moving average array in setup and the main moving average calculation in the loop function eliminates the need for an "if" statement in the main loop to keep the count on how many values are in the array.
Also, this algorithm uses only integer math.
Finally

mavindex++ ; // Point to the next element in the array, now the oldest element.
  mavindex &= sizemask ; // Circle back to 0 if reached size of the moving average  (e.g.  10000 & 01111 (16 & 15) = 00000 (0)  )

Replaces your modulus and my

 if (mavindex=16) mavindex = 15 ;

As I feel it may be faster than both (but I really don't know).

Your comments are welcome.