Show Posts
Pages: [1] 2 3 ... 6
1  Using Arduino / Programming Questions / Re: Add delay to "digitalWrite( ledPin,LOW);" via a pushbutton and resume code on: December 12, 2012, 11:34:56 am

I'm building a lucid dreaming induction device, that while asleep and dreaming would deliver flashing lights to recognize the dream state.
 

How exactly does the Arduino know you are in REM state?
2  Using Arduino / Sensors / Re: Help with signal conditioning on: December 08, 2012, 04:40:02 pm
Yes, I'm coming more or less to the same conclusion.

Since the signal is quite clean to begin with, the next thing will be to see if an 8 period average gives a shorter delay with an acceptable low number of false positives/negatives.

Interesting (and very frustrating) the portion of sketch that sends the MIDI signal to the serial would not work unless i put a delay (10) ; In the main loop.
But it will work without the delay, if I Serial.print() ; the data on the serial monitor for debugging.

Go figure.....






3  Using Arduino / Sensors / Re: Help with signal conditioning on: December 07, 2012, 08:52:20 pm
Just wanted to report on my results, for whomever may be interested.

I applied a simple "decision" to the 16 period moving average:

IF moving average > 0  I am blowing on the sensor
IF moving average < 0  I am NOT blowing on the sensor

with the corollary that:

IF moving average == 0 I am doing whatever I was doing before  // No need to actually state

This is the result in graphic form:

The blue line is the sensor data, the red line is the moving average (multiplied by 100 for ease of plotting) and the green line is the result of the decision: 100 I am blowing, 0 I am not blowing.

It's getting accurate, though there are some false positives and false negatives now and then and, in this very example, there are 86 ms of delay from the beginning of the decay (when I stop blowing) to the response of the moving average (when the software realized that I stopped blowing).

I'll continue tweaking the software.

If there is interest I'll keep posting updates.

 
4  Using Arduino / General Electronics / Re: Superglue instead of solder? on: December 05, 2012, 05:38:19 pm
Yes, I am aware that soldering is the ultimate solution, but I was wondering about alternatives.
I know how to solder, but I am not very proficient.... I guess I'll just practice  smiley-grin
5  Using Arduino / Sensors / Re: Help with signal conditioning on: December 05, 2012, 05:18:49 pm
Thanks!
6  Using Arduino / General Electronics / Re: Superglue instead of solder? on: December 05, 2012, 05:16:06 pm
Yea it's non-conductive at least after it's 'dried' and would not be a viable electrical connection. Also I used CA based glues a lot in R/C aircraft years ago and while the glue is amazing in many properties I found such glued connections can just sudden fail given enough time. as in many months or a couple of years.

Thanks, I figured there must have been a reason for not using it but I did not know what it was.
7  Using Arduino / General Electronics / Superglue instead of solder? on: December 05, 2012, 04:39:49 pm
I just had either the most brilliant or the stupidest idea (please be kind in your reply  smiley-grin )

I am not at all skilled with the soldering iron and I noted that you can make your wire/post/header fit snugly into a perfboard.

Could I glue them with a drop of superglue to make a permanent contact (and save the solder)?

Is the superglue  conductive?  if not it may insulate the contacts, if it is it may create shorts if it spills on adjacent holes. Maybe that's why it is not (widely) used.

Thanks
8  Using Arduino / Sensors / Re: Help with signal conditioning on: December 05, 2012, 04:29:44 pm
There are two issues: signed vs. unsigned, and integer math.

Which one are you referring to?

The value I am averaging is a signed integer which varies roughly between -5 and +5 (but in theory could be more) and the 16 periods moving average (in my tests) is very often 0 with some peaks between -2 and +2.

Thanks
 
9  Using Arduino / Sensors / Re: Help with signal conditioning on: December 05, 2012, 07:17:16 am
@ dhenry.

Thanks for the clarification!

In my particular case, new_data is often = 0 as it is the difference between two sensors values taken at very short interval, so it won't work for me.

your original suggestion:

Code:
mav = mav + (new_data - mav) / 16 ;

is not affected by this problem, or is it?

Thanks
10  Using Arduino / Sensors / Re: Help with signal conditioning on: December 04, 2012, 02:35:03 pm

So would this in effect be acting as a low pass filter on the signal? If so how is the 16 related to the 'corner frequency of the effective filtering action, or is that more a function of how often the statement is executed per time unit?


Ah... I yield to dhenry and robtillaart (not that I would not know the answer....)  smiley-red

 
11  Using Arduino / Sensors / Re: Help with signal conditioning on: December 04, 2012, 01:49:49 pm
A fast moving average would be something like this:

mav = (1-alpha)*mav + alpha * new_data;

where 0<alpha<1 as a weight for new observations. The smaller alpha is, the longer memory mav has of historical data.

If you pick alpha to be 1/2^n, the math gets considerably easier as you can simply shift. For example, for alpha = 1/16:

mav = mav + (new_data - mav) / 16.

essentially, 1 subtraction, 1 shift, 1 increment.


That's very elegant.
It eliminates the need for an array to keep track of the last "n" numbers (and the ++ and &= operations on the counter) and eliminates the initializing function altogether.

Thanks!

P.S. Question for the C++ wiz. Would:

mav += ((new_data - mav) / 16) ;

work? faster? are the external () necessary?


12  Using Arduino / Sensors / Re: Help with signal conditioning on: December 03, 2012, 05:58:11 pm

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


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

Code:
/*  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

Code:
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
Code:
if (mavindex=16) mavindex = 15 ;
As I feel it may be faster than both (but I really don't know).

Your comments are welcome.
13  Using Arduino / Sensors / Re: Help with signal conditioning on: November 30, 2012, 03:36:00 pm

Boy, I definitely have to spend more time in the playground smiley.

Though I still don't know how PID helps me.
In other words, I don't know what the note should be, the input value is supposed to tell me that.

Am I missing something?

Thanks
14  Using Arduino / Sensors / Re: Help with signal conditioning on: November 30, 2012, 12:50:14 pm
Alternatively, you can introduce some derivative gain, similar to a PID controller, for this.

I find your suggestion interesting.
I found that:
http://en.wikipedia.org/wiki/PID_controller#Pseudocode

While the math is way above my head, in the bottom they put a simple pseudocode, which they said is suited for MCUs:

Code:
previous_error = 0
integral = 0
start:
  error = setpoint - measured_value
  integral = integral + error*dt
  derivative = (error - previous_error)/dt
  output = Kp*error + Ki*integral + Kd*derivative
  previous_error = error
  wait(dt)
  goto start

but I am not sure about the whole idea behind it though it resembles the derivative idea of Rob.

Also, how to determine the dt (time between measurements) given that I need the fastest response possible. Should I eliminate the "wait" statement and make dt just  = millis() - last_millis()  ?
Kp, Ki and Kd are tuning constants and that, I suspect, is more a matter of trial and errors.

How could I apply it to my problem (slow decay curve)?

Thanks
15  Using Arduino / Sensors / Re: Help with signal conditioning on: November 30, 2012, 10:52:40 am
Rob,

>>> Does it solve your problem now?

I have to try in practice in my application see if the result is acceptable.
In a "perfect" wind controller, I should be able to detect a gradual decrescendo, that is the player blowing softer and softer to make the sound fade away gradually but I don't know how I would differentiate that from the slow decay that I see when I stop blowing altogether.

>>> Otherwise you might need the second derivative too.

By second derivative you mean something like:

Code:
newderivative = oldvalue - newvalue ;
secondderivative = oldderivative - newderivative ;
oldderivative = newderivative ; // Remembers the previous one

>>> Missing in the graph is the square wave, derived from the first derivative. Would make the picture complete.

Sorry, I did not include it because it does not show very well, But I am attaching it now. I am also attaching the actual Excel in case you are interested (the 8 periods moving average was calculated in the spreadsheeti itself).

>>> Maybe smoothing the original signal with a moving average is better than smoothing the derivative (should become smoother automatically).

I did not think about that because the actual signal seems clean enough but maybe a 2 or 4 period moving average of the signal will yield a clean derivative as well and be faster to show a true change

>>> seen this class - http://arduino.cc/playground/Main/RunningAverage - ?

No, I haven't. It does look very useful. smiley

My approach is very similar to yours in:
Code:
long runningAverage(int M)
which avoids the need for floating math.

with the difference that I use two distinct routines, one for initializing the array during setup() and one to update the actual running average from loop().
That has the advantage of eliminating
Code:
 if (count < LMSIZE) count++;
so that the division is always by 16 (in my case) which could be replaced by a rightward 4 bit shift (though if I understand correctly, the compiler is smart enough to make the replacement).
Also, is:
Code:
 index = index % LMSIZE;

More efficient than:
Code:
index++ ;
if (index >= LMSIZE) index = 0 ; // If LMSIZE is 16 index cannot be more than 15


I can post the code for my little functions  if of interest (and if you'd like to comment on it)

Thanks again



Pages: [1] 2 3 ... 6