Pulse sensor to max/msp (or Max4live)

mikele s's icon

Hello, Could anyone share a patch or help out in getting "pulse sensor" (from pulsesensor.com) to work on max msp or max4live.
my goal is to get the BPM data and also the "Pulse On/Off" so i can trigger some midi files : ) kinda lost here:

set up:
https://pulsesensor.com/products/pulse-sensor-amped
Arduino UNO board.
arduino is loaded with Pulse Sensor Amped 1.5 (also have 1.4 version) with the "true/false" changes.
Max has a simple patch for collecting serial info but only getting 255 with glitches. not bpm info

Source Audio's icon

After reading ALL the same threads and questions You posted within last few hours, and having a look at the screenshot,
I would say that You have no idea what arduino sends out on serial port, and also don't know how to read serial port in max.
So where do You want to start solving the problem ?
First learning arduino stuff, so to understand what is going on ?
Somehow I understand why nobody wanted to reply here.
---------
Send info on what You have on Arduino side, and no link to some sites
where one has to go, dig arround and make research abot ongoings.
That's Your job.
If it is clear what aduino is sending, than maybe someone will help You read it in max.

mikele s's icon

Tnx for the somewhat strong reply. (i feel a bit offended)
yes i posted in a few threads that brought up the issue, and i followed all the info shared on them and similar issues had occurred... time has passed and i am asking if anyone can share info or patch or link to a working set up.
say like in this thread:
https://cycling74.com/forums/pulse-sensor-amped-max
ive tried the pulse sensor arduino files v.1.4 and 1.5 with recommended edits.
ive got the patch on max to work but the data is glitchy and it seems some people managed to get the exact BPM read out, and yes, im lost to how to fix that and would benefit from some guidance.

yes, im a novice but ive made many art+interactive projects through the years and can figure things out pretty well.
this time with the pulse sensor i have very short time to develop the art work and was asking for help from the hive mind.

set up: Arduino UNO board. arduino is loaded with Pulse Sensor Amped 1.5 (also have 1.4 version) with the "true/false" changes. Max has a simple patch for collecting serial info but only getting 255 with glitches. not bpm info

Source Audio's icon

Now I don't own that pulse sensor, and also don't know what Your arduino is sending over serial port.
That's why I asked You to write here what exactly arduino is supossed to send.
Once You know what that is, one can organise a way to read it.
So what is arduino sending, exactly ?
As soon as You provide the details, I will be glad to help as much as I can.

mikele s's icon

Ok,
arduino is sending serial data and this is what i see in the print window.
(picture attached below)

here is the Arduino code:

/* Pulse Sensor Amped 1.5 by Joel Murphy and Yury Gitman http://www.pulsesensor.com

---------------------- Notes ---------------------- ----------------------
This code:
1) Blinks an LED to User's Live Heartbeat PIN 13
2) Fades an LED to User's Live HeartBeat PIN 5
3) Determines BPM
4) Prints All of the Above to Serial

Read Me:
https://github.com/WorldFamousElectronics/PulseSensor_Amped_Arduino/blob/master/README.md
---------------------- ---------------------- ----------------------
*/

#define PROCESSING_VISUALIZER 1
#define SERIAL_PLOTTER 2

// Variables
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13; // pin to blink led at each beat
int fadePin = 5; // pin to do fancy classy fading blink at each beat
int fadeRate = 0; // used to fade LED on with PWM on fadePin

// Volatile Variables, used in the interrupt service routine!
volatile int BPM; // int that holds raw Analog in 0. updated every 2mS
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // int that holds the time interval between beats! Must be seeded!
volatile boolean Pulse = false; // "True" when User's live heartbeat is detected. "False" when not a "live beat".
volatile boolean QS = false; // becomes true when Arduoino finds a beat.

// SET THE SERIAL OUTPUT TYPE TO YOUR NEEDS
// PROCESSING_VISUALIZER works with Pulse Sensor Processing Visualizer
// https://github.com/WorldFamousElectronics/PulseSensor_Amped_Processing_Visualizer
// SERIAL_PLOTTER outputs sensor data for viewing with the Arduino Serial Plotter
// run the Serial Plotter at 115200 baud: Tools/Serial Plotter or Command+L
static int outputType = PROCESSING_VISUALIZER;

void setup(){
pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat!
pinMode(fadePin,OUTPUT); // pin that will fade to your heartbeat!
Serial.begin(115200); // we agree to talk fast!
interruptSetup(); // sets up to read Pulse Sensor signal every 2mS
// IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE,
// UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN
// analogReference(EXTERNAL);
}

// Where the Magic Happens
void loop(){

serialOutput() ;

if (QS == true){ // A Heartbeat Was Found
// BPM and IBI have been Determined
// Quantified Self "QS" true when arduino finds a heartbeat
fadeRate = 255; // Makes the LED Fade Effect Happen
// Set 'fadeRate' Variable to 255 to fade LED with pulse
serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial.
QS = false; // reset the Quantified Self flag for next time
}

ledFadeToBeat(); // Makes the LED Fade Effect Happen
delay(20); // take a break
}

void ledFadeToBeat(){
fadeRate -= 15; // set LED fade value
fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers!
analogWrite(fadePin,fadeRate); // fade LED
}

Source Audio's icon

Now that's finaly some more info.
The sketch is over complicated for what it should do, and in first place makes confusion with serial output type selection which is handled by sketch AllSerialHandling.ino.
But now to the thing - You can see from the max serial print that arduino sends a character S followed by reading of the value. (Raw Analog Reading).
When BPM gets calculated from several readings You should also receive BPM followed by the calculated value, and IBI ( time between beats, i guess in ms).
To route the prefix S ( raw analog read) B ( BPM ) and Q (IBI) You must split it before itoa conversion.
You get that errors in max window because change objects is for ints only, not text.
Here is the patch which routes letters S, B and Q to 3 outlets.

Max Patch
Copy patch and select New From Clipboard in Max.

And if all You want is BPM value, Arduino sketch can be simplifed, and
that serial handling sketch can be removed.

mikele s's icon

thank you for the great explanation and patch.

with loading the patch (serial C input is my arduino) its starts reading.
ive check with Print object:
serial outputs = numbers list 10 to 60 range
sel 13 = sends bangs
zl group = sends number lists like "10 83 55 49 55"

But nothing is showing after that.
do i need to change the numbers in the "route" object ?
nothing seems to come past the "route" object.
the second number seems to change according to my heart beat ( 83 changes to a lower number in what seems to be a heart beat)

does the "ASCII Code for S B Q" need to be connected to anything ?




Source Audio's icon

I see , I forgot to add 10 to sel, sorry
I'll upp the patch in a moment

Max Patch
Copy patch and select New From Clipboard in Max.

Source Audio's icon

83 is S , so it represents raw analog readings.
66 is B and that is the BPM
81 is Q and that is beat interval in ms I believe
I did not add any smoothing of data, You can do that as You wish.
And the 10 and 13 are ASCII numbers for line feed and carriage return,
so we use 13 as line end to bang zl group to output what's been collected so far.

mikele s's icon

Brilliant !
its working great.
Thank you so much for helping , my heart rate is lower now :)
ive learned a lot and will dive deeper.

so just for others who might benefit.
with the help of SOURCE AUDIO.
the setup inve got that works:
Arduino Uno board
loaded with
PulseSensorAmped_Arduino_1.5.0
to max msp, with your (SOURCE AUDIO) great patch.
and here with an added simple midi out... ill work on the other configurations on Ableton side soon.
(picture: both BPM and IBI give pulse and BPM could set Ableton project tempo as well)



Source Audio's icon

I am glad that everything works to Your expectations.
There is nothing so special about that patch, but arduino
side could have been done in a bit easier way.


Trina Cooper's icon

Okay, so I am interested in a similar system to use with dancers, which would pick a heart rate and send the date to Ableton Live. I would like use a fitbit, a sensor belt or something instead of an Arduino unit. The dancer move and sweat which makes the Arduino problematic. Does anyone know of a heart rate monitor system that can be worn by dancers and picked up by Ableton or max msp. It seems like such a unit should exit but most of what I have seen is proprietary. I am assuming that this is because the micro controllers on pro-sumer and consumer units are hard coded to talk to their intended aps which seem to live on phones. Thanks if anyone know of a good work around here.

andrea piccinni's icon

hi! i follow every passage post in thread here with the same patch of max and code arduino but i'm still having problem to get any value on RAW BPM IBI here's the Arduino Code, (if I remove the serial handling sketch it says that the serial output is not declared) the patch of max is the same posted above.
/* Pulse Sensor Amped 1.5 by Joel Murphy and Yury Gitman http://www.pulsesensor.com

---------------------- Notes ---------------------- ----------------------
This code:
1) Blinks an LED to User's Live Heartbeat PIN 13
2) Fades an LED to User's Live HeartBeat PIN 5
3) Determines BPM
4) Prints All of the Above to Serial

Read Me:
https://github.com/WorldFamousElectronics/PulseSensor_Amped_Arduino/blob/master/README.md
---------------------- ---------------------- ----------------------
*/

#define PROCESSING_VISUALIZER 1
#define SERIAL_PLOTTER 2

// Variables
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13; // pin to blink led at each beat
int fadePin = 5; // pin to do fancy classy fading blink at each beat
int fadeRate = 0; // used to fade LED on with PWM on fadePin

// Volatile Variables, used in the interrupt service routine!
volatile int BPM; // int that holds raw Analog in 0. updated every 2mS
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // int that holds the time interval between beats! Must be seeded!
volatile boolean Pulse = false; // "True" when User's live heartbeat is detected. "False" when not a "live beat".
volatile boolean QS = false; // becomes true when Arduoino finds a beat.

// SET THE SERIAL OUTPUT TYPE TO YOUR NEEDS
// PROCESSING_VISUALIZER works with Pulse Sensor Processing Visualizer
// https://github.com/WorldFamousElectronics/PulseSensor_Amped_Processing_Visualizer
// SERIAL_PLOTTER outputs sensor data for viewing with the Arduino Serial Plotter
// run the Serial Plotter at 115200 baud: Tools/Serial Plotter or Command+L
static int outputType = SERIAL_PLOTTER;

void setup(){
pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat!
pinMode(fadePin,OUTPUT); // pin that will fade to your heartbeat!
Serial.begin(115200); // we agree to talk fast!
interruptSetup(); // sets up to read Pulse Sensor signal every 2mS
// IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE,
// UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN
// analogReference(EXTERNAL);
}

// Where the Magic Happens
void loop(){

serialOutput() ;

if (QS == true){ // A Heartbeat Was Found
// BPM and IBI have been Determined
// Quantified Self "QS" true when arduino finds a heartbeat
fadeRate = 255; // Makes the LED Fade Effect Happen
// Set 'fadeRate' Variable to 255 to fade LED with pulse
serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial.
QS = false; // reset the Quantified Self flag for next time
}

ledFadeToBeat(); // Makes the LED Fade Effect Happen
delay(20); // take a break
}

void ledFadeToBeat(){
fadeRate -= 15; // set LED fade value
fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers!
analogWrite(fadePin,fadeRate); // fade LED
}

Source Audio's icon

You can't simply use serial object initiated as c or port usbmodem1411
That was set for specific arduino board on that used OS.
So in first place you need to get the port or name of the arduino
board to establish communication with max.
If that is done and ok, and you still have no data,
than maybe you use incompatible arduino board or one that needs some
changes to work with that library.
By the way there is a new pulse sensor library collection,
did not test it myself though
https://github.com/WorldFamousElectronics/PulseSensorPlayground

Another thing is to use working pulse sensors and to mount them
correctly.
There were quite few non-functioning sensors on sell from china

andrea piccinni's icon

All connections i did with my arduino are all working , getting values to my serial and monitor plotter, all the system work inside arduino but not in max , is strange how actually the message port c and port usbmodem 142101 was working before, in the sense that the port was recognized, meanwhile now is not, how can i check the port name of my arduino?

andrea piccinni's icon

this is the All Serial Handling Code, maybe something wrong here?
///////// It's Changeable with the 'outputType' variable
///////// It's declared at start of code.
/////////

void serialOutput(){ // Decide How To Output Serial.
switch(outputType){
case PROCESSING_VISUALIZER:
sendDataToSerial('S', Signal); // goes to sendDataToSerial function
break;
case SERIAL_PLOTTER: // open the Arduino Serial Plotter to visualize these data
Serial.print(BPM);
Serial.print(",");
Serial.print(IBI);
Serial.print(",");
Serial.println(Signal);
break;
default:
break;
}

}

// Decides How To OutPut BPM and IBI Data
void serialOutputWhenBeatHappens(){
switch(outputType){
case PROCESSING_VISUALIZER: // find it here https://github.com/WorldFamousElectronics/PulseSensor_Amped_Processing_Visualizer
sendDataToSerial('B',BPM); // send heart rate with a 'B' prefix
sendDataToSerial('Q',IBI); // send time between beats with a 'Q' prefix
break;

default:
break;
}
}

// Sends Data to Pulse Sensor Processing App, Native Mac App, or Third-party Serial Readers.
void sendDataToSerial(char symbol, int data ){
Serial.print(symbol);
Serial.println(data);
}

Source Audio's icon

You could have posted what arduino board is in use.
------------
Only one software at a time can communicate with serial port.
Before running max patch, close serial monitor in arduino IDE.
Same the other way arround, if you want to upload code,
close max serial port.
------------
print message to serial object outputs all available
devices and their abreviations and port names to max console.

all infos in help file and reference for serial object.
-------
If you get the sensor data ok in arduino serial monitor,
than it should work for max too.
If you are not shure about changes done, start with original unmodified
arduino libs and code.

andrea piccinni's icon

so this is the situation, in arduino everything work great in serial and monitor plotter, my arduino uno board blink at tempo with my heartbeat, but..
when i close arduino and i turn on max, the bang is blinking really fast even if i disconnect my arduino uno board (not in time with my heart rate) and the port of my arduino uno get recognise as a portc usbmodem142101, the print works from the outlet of serial, but not from the outlet of zl group and the values are always around 255 (fade rate in arduino) no number (0) in the float number,
what it can be the issue?

Source Audio's icon

Maybe you are sending more from arduino than it is expected...
try increasing that zl group to something bigger,
it should actually not output anything itself, but only when triggered by new line feed.
try zl 1024 group 1024

Also can you make a screenshot of arduino serial monitor ?
Not plotter but serial monitor showing the 3 values

Source Audio's icon

And you should not disconnect arduino while max serial object is linked to it.
use message close to serial object to disconnect arduino from it.
I just realised that in original post from Mikele this was set :
static int outputType = PROCESSING_VISUALIZER;

In your patch
static int outputType = SERIAL_PLOTTER;

that makes the difference
I made that max patch for exactly what was in original arduino sketch.
So keep it same and it should work.
---------------------------

If you only need bpm, try this simple code,
no libs or whatever else stuff is needed :

int rawValue;
bool heartbeatDetected(int IRSensorPin, int delay)
{ static int maxValue = 0; static bool isPeak = false; bool result = false; rawValue = analogRead(IRSensorPin); rawValue *= (1000/delay);
if (rawValue * 4L < maxValue) { maxValue = rawValue * 0.8;}
if (rawValue > maxValue - (1000/delay)) {if (rawValue > maxValue) { maxValue = rawValue;}
if (isPeak == false) {result = true;} isPeak = true;}
else if (rawValue < maxValue - (3000/delay)) {isPeak = false; maxValue-=(1000/delay);
} return result;}
int analogPin = 0;
void setup(){ Serial.begin(115200);}
const int delayMsec = 60;
void loop(){ static int beatMsec = 0; int heartRateBPM = 0;
if (heartbeatDetected(analogPin, delayMsec)) {heartRateBPM = 60000 / beatMsec;
digitalWrite(13,HIGH); Serial.println(heartRateBPM); beatMsec = 0;}
else {digitalWrite(13,LOW);}
delay(delayMsec);
beatMsec += delayMsec;
}
--------------------
this should send only BPM value to serial
max patch :

Max Patch
Copy patch and select New From Clipboard in Max.


andrea piccinni's icon

i try zl 1024 group 1024 but still don't work , when I upload the code to my arduino board then I close the serial monitor and arduino program , here the file of arduino serial monitor

arduino.mov
video/quicktime 1.05 MB

Source Audio's icon

exactly - read my last post - you selected wrong serial output type.
you have 3 floats, comma separated in serial monitor,
max patch is not set to receive that.

andrea piccinni's icon

yes! thank you so much for the help! it's working!

andrea piccinni's icon

Hi Source Audio ! everything is working great but I'd like to customize the patch to add other futures, could you write me please what's going on in every line of the latest Arduino patch you post in this thread? (the sketch I'm using right now) it could be helpful to understand and do stuff by my own , thanks! cheers

Source Audio's icon

I don't have time to teach arduino online...
But am willing to provide more info.
Pasting raw text code into this text field
does not allways respect line break...
That's why the sketch is looking a bit disordered
------------
the top part is a peak detector, which is usually part of some pulse sensor libs
// Peak Detector
int rawValue;
bool heartbeatDetected (int IRSensorPin, int delay){
static int maxValue = 0;
static bool isPeak = false;
bool result = false;
// Read voltage value from the phototransistor and temporarily store in the rawValue variable
rawValue = analogRead (IRSensorPin);
rawValue * = (1000 / delay);
// If the current value deviates too much from the last maximum value reset the MaxValue
if (rawValue * 4L <maxValue) {maxValue = rawValue * 0.8; }
// Detect new peak
if (rawValue> maxValue - (1000 / delay)) {if (rawValue> maxValue) {maxValue = rawValue;}
if (isPeak == false) {result = true;}
isPeak = true;}
else if (rawValue <maxValue - (3000 / delay)) {isPeak = false;maxValue - = (1000 / delay);}
return result;
}
// That's the end of Peak Detector

// set variables:
int analogPin = 0; // set sensor pin to A0
const int delayMsec = 60; // set sampling division
//Initialise serial port and baud rate
void setup(){Serial.begin(115200);}

void loop(){ static int beatMsec = 0; int heartRateBPM = 0; // reset on each loop start
// If HB detected - calculate BPM , light the LED, print BPM value to serial and reset beatMsec to zero
if (heartbeatDetected(analogPin, delayMsec))
{heartRateBPM = 60000 / beatMsec;
digitalWrite(13,HIGH); Serial.println(heartRateBPM); beatMsec = 0;}
// If no HB detected

else {digitalWrite(13,LOW);}
delay(delayMsec); // delay the loop
beatMsec += delayMsec; } // add beatMsec and delayMsec
--------------------------

Source Audio's icon

P.S. You should analyse the several pulse sensor libs just to get an idea
about interrupts, and so avoid problems with adding functions to existing code