Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pulse sensor interfering with other sensor readings #66

Closed
sorexy opened this issue Jul 23, 2018 · 13 comments
Closed

Pulse sensor interfering with other sensor readings #66

sorexy opened this issue Jul 23, 2018 · 13 comments

Comments

@sorexy
Copy link

sorexy commented Jul 23, 2018

Greetings,

I have encountered a rather strange issue while using two sensors and was hoping for some help. The two sensors of which I speak are as follows:

  1. a Galvanic skin response sensor (measuring skin conductivity)
    link: http://wiki.seeedstudio.com/Grove-GSR_Sensor/

  2. the Pulse sensor to measure heart rate
    https://pulsesensor.com/

So, the issue is as follows:

When i connect the sensors to analog slots (GSR on A0, and pulse sensor on A2 specifically), I experience readings that seem to suggest that the both data streams from the GSR and pulse sensor are interfering with one another (i.e. the pulse readings influence the GSR sensor's readings). Please see the images for clarification.

https://imgur.com/a/XO4amjk

In the images, the pulse readings is the orange curve, and the GSR reading the dark blue curve.

I suspect it is interference within the Arduino and because all of these screenshots were taken while I was not wearing the GSR sensor.

One observation I have made was that the interference only starts when the pulse rate (orange curve) increases it's amplitude (as shown in attachment 2). As we can see, during low amplitude readings, no interference is present (e.g. in attachment 3). Similarly, in attachment 4, we notice the only time the GSR reading spikes up (dark blue curve) is when a large amplitude pulse reading simultaneously occurs (orange curve).

Please find the code I am using below.

#define USE_ARDUINO_INTERRUPTS false
#include <PulseSensorPlayground.h>

const int GSR=A0;
const int PULSE_INPUT=A2;

const int OUTPUT_TYPE = SERIAL_PLOTTER;
const int THRESHOLD = 550;  
int sensorValue=0;
int gsr_average=0;

byte samplesUntilReport;
const byte SAMPLES_PER_SERIAL_SAMPLE = 10;

/* load pulseSensor library */
PulseSensorPlayground pulseSensor;

void setup() {
  Serial.begin(115200);
  
  /* ===== Setting up the pulse sensor ===== */
  pulseSensor.analogInput(PULSE_INPUT);
  pulseSensor.setSerial(Serial);
  pulseSensor.setOutputType(OUTPUT_TYPE);
  pulseSensor.setThreshold(THRESHOLD);
  // Skip the first SAMPLES_PER_SERIAL_SAMPLE in the loop().
  samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
}

void loop() {

    /* ========== Collecting data from the GSR sensor ========== */
    long sum=0;
    //Average 10 measurements to reduce noise
    for(int i=0;i<10;i++) {          
      sensorValue=analogRead(GSR);
      sum += sensorValue;
      }
   gsr_average = sum/10;
 
  if (pulseSensor.sawNewSample()) {
    /*
       Every so often, send the latest Sample.
       We don't print every sample, because our baud rate
       won't support that much I/O.
    */
    if (--samplesUntilReport == (byte) 0) {
      samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;

      /* outputs GSR readings along with pulse readings in the same line, separated by commas */
      pulseSensor.outputSample(gsr_average);
    }
  }
}

Any help would be greatly appreciated! I have been trying to figure this out for a while now..

EDIT: Fixed image URL

@biomurph
Copy link
Contributor

First a couple of things.

I can't see the images that you link to.
What hardware are you targeting?
You need pulseSensor.begin() in the setup to start the Pulse Sensor reading correctly.

Finally, you can't use the ouputSample function the way that you want to. The parameter that outputSample takes is the number of Pulse Sensors you have, if you have more than one. You will have to put in your own line that prints the gsr_average and the comma to print to the serial plotter.

Let me know if that fixes it.

@sorexy
Copy link
Author

sorexy commented Jul 23, 2018

Hi there,

Thank you very much for your response! I've fixed the URL to the images and it should be working now.

I am currently using the Genuino 101 for this project.

I added pulseSensor.begin() to the setup (shown below), but it still produces the interference described.

void setup() {
  Serial.begin(115200);
  
  /* ===== Setting up the pulse sensor ===== */
  pulseSensor.analogInput(PULSE_INPUT);
  pulseSensor.setSerial(Serial);
  pulseSensor.setOutputType(OUTPUT_TYPE);
  pulseSensor.setThreshold(THRESHOLD);
  // Skip the first SAMPLES_PER_SERIAL_SAMPLE in the loop().
  samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
 
 pulseSensor.begin();
}

With regards to the outputSample function, i've actually overloaded the default one and didn't think it would cause any problems. I have removed it though and just added prints to see if this was the problem. Unfortunately, the issue still persists.

    if (--samplesUntilReport == (byte) 0) {
      samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;

      /* outputs GSR readings along with pulse readings in the same line, separated by commas */
      Serial.print(gsr_average);
      Serial.print(',');
      pulseSensor.outputSample();
    }

I look forward to hearing from you.

@biomurph
Copy link
Contributor

That is very strange that your A0 input is affected by your A1 input...
Or maybe not. I don't know much about the genuino 101 and how it does analog read stuff.
Here's some things to try.

Move the Pulse Sensor to a more physically distant analog input and see if you have the same issue?

Your GSR readings don't need to be happening all the time. Try doing them only occasionally? There is a variable called isInsideBeat that you can access with pulseSensor.isInsideBeat() it returns true if the pulse wave is above the threshold, and false when it's not. If the weird crosstalk continues when you move the pulse sensor physically far away, you could access that boolean and only check your GSR when it returns false. LMK if that works.

@sorexy
Copy link
Author

sorexy commented Jul 24, 2018

Moving the pulse sensor further from the GSR sensor did not stop the interference unfortunately. With regards to the isInsideBeat() function, I tried it and noticed something completely bizzare as well. When the amplitudes of the PPG waveform were not so strong, the signals would always cross over the threshold, according to the isInBeat() function. The threshold is set to the default (550 i believe).

However, here comes the weird part, when the waveform starts ramping up in amplitude and causes interference in the GSR readings, the isInBeat() seems to switch between True/False states synchronously with the interference patterns. Here is a screenshot of the readings

https://imgur.com/a/yynnmL3

On another note, do you think it could be a power supply issue?

@biomurph
Copy link
Contributor

This all makes sense.
First point to make is that the threshold value varies when there is a steady beat and takes the value of 1/2 of the pulse amplitude. That is to help with noise and to get closest to the 'moment of heart beat' according to people smarter than me...
When the signal crosses the threshold, the isInsideBeat will return true. Your graph is really nice and shows how those variables and the algorithm are working, cool!
But, you still have noise in your GSR....

I took a look at the grove sensor, and it's output is buffered by a low pass filter. The resistor that is used is 1M, so that means that the grove sensor has a pretty high impedance output. The Pulse Sensor, however, has a very low impedance output. So the Pulse Sensor is sending current into the system that is effecting the grove output. There's a couple of things to try to mitigate this problem.

First option, fix it in code. As mentioned in my last comment, the GSR values really don't change that fast, so you don't need to measure them as often as you are doing. You can easily avoid the current noise in the GSR signal by only measuring it when the isInsideBeat() returns false.

Second option, fix it in hardware. You can try to put a resistor in series with the Pulse Sensor signal. That would reduce the amount of current bouncing around, and should dampen the noise in the GSR signal. With the sketch running, try a few different resistors, like 1K, 10K, 100K, 1M, and see what happens to the signals in real time.

LMK what happens.

@yury-g
Copy link
Member

yury-g commented Jul 26, 2018 via email

@sorexy
Copy link
Author

sorexy commented Jul 28, 2018

Hi guys,

Thanks for the responses.

So I tried implementing in code to only measure the GSR when isInsideBeat() is false, but the interference still persists. It seems rather bizzare. I've also tried to make it read and report the GSR values only when the pusle sensor PPG waveform is lower than the baseline GSR reading. Still interference. I even tried adding delays of 10msec before and after taking GSR readings, but to no avail. I am currently unable to fix it via hardware as I do not possess the required components.

With regards to which BPM project I am using, I am using BPM Alternative. The first one does not work for me unfortunately.

Many thanks.

@biomurph
Copy link
Contributor

@sorexy please share the code you are using. I don't see how you could still get interference when you are measuring GSR when the isInsideBeat is false.

@sorexy
Copy link
Author

sorexy commented Jul 30, 2018

Yes of course,

I tried this

  if (pulseSensor.sawNewSample()) {
  
    if (!pulseSensor.isInsideBeat()){
      long sum=0;
      for(int i=0;i<10;i++) {          
        sensorValue=analogRead(GSR);
        sum += sensorValue;
        }
      gsr_average = sum/10;
      }
    
    if (--samplesUntilReport == (byte) 0) {
      samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
      
      /* outputs GSR readings along with pulse readings in the same line, separated by commas */
        Serial.print(gsr_average);
        Serial.print(',');
        pulseSensor.outputSample();
    }
  }

and

  if (!pulseSensor.isInsideBeat()){
    long sum=0;
    for(int i=0;i<10;i++) {          
      sensorValue=analogRead(GSR);
      sum += sensorValue;
      }
    gsr_average = sum/10;
    }

  if (pulseSensor.sawNewSample()) {
    if (--samplesUntilReport == (byte) 0) {
      samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
      
      /* outputs GSR readings along with pulse readings in the same line, separated by commas */
        Serial.print(gsr_average);
        Serial.print(',');
        pulseSensor.outputSample();
    }
  }

The first reduced the interference significantly, but not eliminated it. In fact, sometimes the interference comes in the form of a negative spike.

The second did not reduce interference.

Please check here for images

https://imgur.com/a/CzUbYpi

@biomurph
Copy link
Contributor

I can see by the images you shared that you are definitely getting good GSR when you're outside of the beat, but when you are measuring GSR just after isInsideBeat goes false (right after the beat) you are catching the last bit of the noise that is in the signal. So, you need to only use (or measure) GSR that is clean before the isInsideBeat turns true.

Have you tried to put a resistor in series with the Pulse Sensor purple wire?

@sorexy
Copy link
Author

sorexy commented Aug 1, 2018

So I tried the resistors, only the 1M resistor seemed to reduce the interference but not eliminated it. I have decided to use two arduinos instead.

@biomurph
Copy link
Contributor

biomurph commented Aug 2, 2018

@sorexy bummer about that.

One last thing to try in hardware would be to buffer the GSR signal with an op amp set up to be a voltage follower. That would make the signal from the GSR much lower impedance, and it will have a fighting chance against the Pulse Sensor signal.

@yury-g
Copy link
Member

yury-g commented Oct 4, 2018

more or less at resolution.

@yury-g yury-g closed this as completed Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants