kurtosis calculations on an analog signal

Hey! I am very new to arduino, so please bear with me. I am working on a project where I am taking a sine wave (1V amplitude, 100 Hz) from a function generator, sending it through to my arduino uno by using the ReadAnalogVoltage example, performing kurtosis on a 30 second interval of these samples, and then wirelessly transmitting this information to a nearby laptop using XBee protocol.

What I am struggling with is programming the Arduino. After getting the input voltages from the ReadAnalogVoltage, I have no idea how to program the board so it calculates the kurtosis over a 30sec interval and then how to send those values. Any help or links would greatly help. I appreciate it.

What formula would you use to measure kurtosis, why are you measuring it and how does it apply to sampling a sine wave?

Pete

The overall project will involve taking a chin EMG signal and extracting the Kurtosis, RMS, and Zero Crossings from the analog signal and sending these values wirelessly to a laptop using XBee. Right now, I am focusing on just finding out how to extract Kurtosis from a sine wave because this is an easy way to test if the kurtosis program on the Arduino Uno is working. The formula I want to use for Kurtosis is
[the sum of deviation scores raised to the fourth power divided by the number of scores] / [the sum of squared deviation scores divided by the number of scores]^2

The formula I want to use for Kurtosis is

How have you computed "the sum of deviation scores". How have you even gotten one "deviation score"?

The blink without delay example will show you how to do something for any desired interval.

I've learnt a new word today, thanks!

So the question is kurtosis applies to a distribution, so what distribution are you sampling,
simply the voltage samples, or something else like phase or amplitude?

What code do you have now - always post your code if you want someone to suggest
improvements or changes!

Is your problem simply how to translate maths into C code?

Yes, I am very new to programming so I am having difficulty translating the math into code. I also can't figure out what code to use to set it so that it takes 30 seconds of sampled data of the analog signal and then performs the math on that 30 sec set.

Ideally, what the output of the system would be is the kurtosis value of every 30 second interval of the analog signal.

I would post my code, but it still needs a lot of work before it can even be critiqued!

This is what I have so far but I know it needs work

unsigned long interval=micros();

void setup() {
Serial.begin(9600);
}

void loop() {
int sensorValue = analogRead(A0);
float voltage= sensorValue * (5.0 / 1024.0);
delay(1);
}

if micros()-interval=30000;
{ ???I NEED TO WRITE THE FUNCTION TO FIND KURTOSIS HERE???
interval=micros()
}

micros() is for microseconds. There are 30,000,000 microseconds in 30 seconds. There are 30,000 milliseconds, as counted by millis(), in 30 seconds. Since timing to the nearest millionth of a second seems unnecessary, you should be using millis().

if micros()-interval=30000;
{ ???I NEED TO WRITE THE FUNCTION TO FIND KURTOSIS HERE???
interval=micros()
}

No. All code needs to be inside a function. The first thing that you need to define is when the 30 second interval starts. Typically, that would involve reading a "Start" switch. When the switch is pressed, you note the time, and the fact that readings are important.

When readings are important, you read the sensor and store the data:

bool takeReadings = false;
unsigned long startedReading = 0;
void loop()
{
   // see if switch is pressed now but wasn't before
   // if so, record the time, and set the flag takeReadings to true.
   if(somethingGoesHere)
   {
       takeReadings = true;
       startedReading = millis();
   }

   if(takeReadings)
   {
      if(millis() - startedReading < 30000)
      {
          // read and store...
      }
      else
      {
          startedReading = 0;
          takeReadings = false;
      }
   }
}

You'd deal with the stored data in the else block.

The state change detection example would be useful for reading the switch.

Thank you so much PaulS. That is very insightful. The only problem I have is I want to continuously take 30 second intervals. For example, I want to output the kurtosis from the start of the recording to 30s, the kurtosis from 30sec-60secs, the kurtosis from 60-90s, etc.

The only problem I have is I want to continuously take 30 second intervals.

So, simple remove the part about reading the switch. Set takeReadings to true, initially. Take readings for 30 seconds. Then, set takeReadings to false, so you can process the data you gathered. When you are done processing the data, set takeReadings back to true.

Now, the next thing to consider is how often you take a reading, and how many readings that translates into, and how much data you need to store for 30 seconds with of readings. Then, consider which Arduino(s) can store that much data. A 328-based Arduino can store less than 1000 readings.

It still doesn't make any sense that you want the kurtosis of a 30 second sample of a sine wave.
What does that tell you?

Pete

This is just for testing of the arduino to make sure the kurtosis program works. Eventually this program will be implemented into a system that will read an EMG and extract the kurtosis and send it to a nearby laptop in order to analyze REM sleep.

PaulS you make a good point of how much data the Arduino could store. Therefore, I have revised my plans on the project. Is there a way where I could use a program similar to that of a running averager and take a certain amount of terms and have it calculate the kurtosis at each moment? How could you write the code for this? Especially with the kurtosis, I don't know how to change the formula into code for the arduino sketch.

If you have a collection of samples, the kurtosis calculation is simple.

The problem here is that you want to collect way too many samples for the memory capacity of the arduino.

In fact, your whole project seems to be misconceived. What are you actually trying to measure ? Some kind of deviation from a proper sine wave, where the peaks of the sinusoidal waveform are "too peaky" ?

How do you write the code for a simple kurtosis calculation then?

I understand that my first method of analyzing thirty seconds of samples would use too much memory for the arduino. Thats why I am hoping to program the arduino to take the kurtosis of lets say 10 samples and function as a moving averager where as it intakes another sample from the front, it gets rid of the sample at the back.

I need to figure out how to write a program that obtains the kurtosis, because in the final project these kurtosis values are valuable to score REM sleep. The kurtosis of the sine wave is simply a test to make sure the kurtosis program is working due to the fact sine waves have a know kurtosis value.

Thank you for your help and comments. I greatly appreciate it.

Do you even know what kurtosis is ?

Yes. It measures the peakedness of a signal and can be defined as either the fourth cumulant divided by the second cumulant or the fourth moment around the mean divided by the square of the variance.

We are using and EMG/EOG test to score REM Sleep and possibly be a prediagnostic for early neurological disorders.

http://petrsu.ru/Chairs/Physiology/JEK.pdf

Kurtosis is one of the needed extracted features.

Thanks.

OK, so they are not sinusoidal signals they are measuring. And, kurtosis does not measure the peakiness of the signal, it measures the peakiness of a histogram showing the distribution of values in the sample. Not the same thing at all.

So, you have your sampled signal. You have your equation defining the kurtosis of the sample numbers. Go for it. Whether that result is at all meaningful, would be for others to decide.

From the arduino point of view, your biggest obstacle is going to be shortage of memory to contain all the data.

For those interested in the theory, a concise and well written summary of statistical analyses of a time series of measurements can be found in the "Handbook of Human Vibration". The kurtosis is defined and a couple of key results are that the kurtosis of a sine wave is 1.5, while the kurtosis of random, i.e. Gaussian-distributed, signals is about 3. The technique can be used for discriminating signal-containing transmissions from noise in radio communications. The formulas would be trivial to implement if the memory to contain the time series were on hand.

Courtesy of Google Books, here is the relevant page: Handbook of Human Vibration - M. J. Griffin - Google Books

An Arduino would be able to handle a few hundred data points, but the question is: would that be enough to give statistically significant results for low-frequency signals like those from electrophysiology measurements?

This is the code I wrote to find the kurtosis of an analog input at pin A0. Does anyone see any problems with this code? I want it to output a value with two decimal places on the serial monitor but for some reason it is not, do you see why?

const int numReadings = 500.00;
float inputPin = A0;
int kurtindex= 0.00;
int kurtVoltages[numReadings];
int total = 0.00;
int average = 0.00;
int sqDevSum = 0.00;
int sum= 0.00;
int kurtosis=0.00;
int stDev4=0.00;
int denominator = 0.00;
int numerator = 0.00;

void setup() {
Serial.begin(9600);
}

void loop() {
kurtVoltages[kurtindex] = analogRead(inputPin);

if (kurtindex >= numReadings);
kurtindex =0.00;

for (int i=0; i < numReadings; i++) {
total += kurtVoltages*;*

  • }*

  • average = total / numReadings;*

for (int i=0; i < numReadings; i++) {
kurtVoltages = kurtVoltages - average;
* }*

for (int i=0; i < numReadings; i++) {
_ sqDevSum += pow(kurtVoltages*, 2);
}*_

int stDev = sqrt(sqDevSum/numReadings);
int stDev4= pow(stDev, 4);

* for (int i=0; i < numReadings; i++) {*
kurtVoltages = pow(kurtVoltages*, 4);*
* }*

* for (int i=0; i < numReadings; i++) {*
_ sum += kurtVoltages*;
}_

_denominator = numReadingsstDev4;
numerator = sum;
kurtosis = numerator/denominator;
kurtosis = kurtosis -3;
Serial.println(kurtosis);
}_

It's good to see the original poster put up some code. It suggests that he's actually interested in a solution.

The posted code doesn't compile. There are repeated references to kurtvoltages, as if it were a variable. But kurtvoltages is an array, and, if it's going to be treated like a single value, it needs an index.

There are logic errors, too, but they can wait. If it doesn't compile, you'll never get any results at all.


[Edit: Add this]
And, until you know what you're doing, please don't try to hook up an analog source - like a signal generator or a biological monitor - to your Arduino. It can be quite easy to damage an analog input when the input voltage goes out of bounds. I suspect that your signal source is centered at zero volts, and that it's negative for at least some of the time. A negative voltage on an analog pin can damage it.


This sounds like an academic assignment. Is it?