So the crucial question for any project -
Well, it is a nice aid for meditation/crystal ball gazing practice;
Besides, one can exercise biofeedback, trying to slow down heartbeat with mental efforts (no instruction given!) and expect improved mind/body balance.
The most important part of this project - pulse sensor from SeeedStudio. And the most important part of this sensor - proprietary controller that comes with sensor:
Controller ( a tiny circuit board inside this white box) generates a short square pulses when heartbeat is sensed. Works like a charm. Looks like this sensor and controller originates from Kyto Electronics product.
This is how assembled project looks:
Here is a video demonstrating how flash color changes with pulse rate:
This is how it works with sensor attached to the ear lobe:
I am trying to change pulse rate with mental effort:
Custom parts and enclosures
Innards
Small green PCB at the lower right - pulse sensor controller (originally was enclosed in a white box connected to pulse sensor)
Schematics:
Code:
//#define DEBUG 1
#include <FastLED.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <RunningAverage.h>
#define DATA_PIN 11
#define CLOCK_PIN 13
#define NUM_LEDS 4
Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();
volatile unsigned long current_time,previous_time, rr_raw, button_time;
unsigned int heart_rate;//the measurement result of heart rate
unsigned int rr, n1,n2;
boolean no_sensor=true;
RunningAverage myRA(10); //initialize running average internal array for 8 measurements
CRGB strip[NUM_LEDS];
int v_delay = 10;
byte n,j1,j2,j3;
int hue;
CRGB v_rgbcolor=CRGB::Blue;
volatile bool data_arrived=false;
byte skip_counter=0;
byte skip_limit=2;
//const byte skip_max=4;
boolean start_flash=true;
boolean show_dot=true;
void setup() {
#ifdef DEBUG
Serial.begin(9600);
#endif
alpha4.begin(0x70);
alpha4.clear();
alpha4.writeDisplay();
pinMode(6, INPUT_PULLUP); //side button setup; for debugging only
FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(strip, NUM_LEDS);
FastLED.clear();
FastLED.show();
delay(50);
for (int i = 0 ; i <3; i++) {
fill_solid(strip,NUM_LEDS,v_rgbcolor);
FastLED.show();
delay(400);
FastLED.clear();
FastLED.show();
delay(400);
}
FastLED.clear();
FastLED.show();
myRA.clear();
n=0;
previous_time=millis();
cli();//stop interrupts
attachInterrupt(0, interrupt, RISING);//set interrupt 0,digital port 2
sei();//allow interrupts
}
void show_Alpha(char c1, char c2,boolean v_show_dot=false) {
alpha4.writeDigitAscii(2, c1);
alpha4.writeDigitAscii(3, c2,v_show_dot);
alpha4.writeDisplay();
}
void loop() {
if (millis()>current_time+3000) {
no_sensor=true;
myRA.clear();
n=0; //when no data reset counter
previous_time=0;
}
else no_sensor=false;
if (no_sensor) {
idle();
}
if (data_arrived){
if (n<11) n++; //dont show first 10 measurements of heart rate
myRA.addValue(rr_raw);
rr=myRA.getAverage();
heart_rate=60000.0/rr;
if (heart_rate<100) {
n1=heart_rate/10+48;
n2=heart_rate%10+48;
}
else {
n1=(heart_rate-100)/10+48;
n2=(heart_rate-100)%10+48;
}
if (n>10) show_Alpha(char(n1),char(n2),show_dot);
else show_Alpha('_','_',show_dot);
show_dot=!show_dot;
if (rr_raw<100)
{
data_arrived=false;
return;
}
v_delay=(rr_raw-50)/35;
//if (v_delay>40) v_delay=25;
#ifdef DEBUG
Serial.print("v_delay=");Serial.println(v_delay);
#endif
hue=map(heart_rate,60,90,0,170);
if (heart_rate>100) heart_rate=100;
fill_solid(strip, NUM_LEDS, CHSV(170-hue,255,255));
#ifdef DEBUG
Serial.print("Skip Counter=");Serial.print(skip_counter); Serial.print("Skip_limit-1=");Serial.println(skip_limit-1);
#endif
if (skip_counter>=skip_limit-1)
{
skip_counter=0;
FastLED.show();
while(j1<35) {
j1++;
fadeLightBy(strip,4,20);
FastLED.show();
delay(v_delay);
// check_button();
}
}
else skip_counter++;
delay(v_delay);
data_arrived=false;
// check_button();
j1=0;
//while(j1<35 && !data_arrived)...
Read more »