1. HRV Calculation
We’ll use the RR intervals (time between heartbeats) to calculate HRV. HRV values will be divided into different ranges, with a focus on accurately detecting stress (low HRV) and relaxation (high HRV).

2. Color Mapping
Stress and relaxation will be mapped to indigo (Pantone 7672 C) and light blue (Pantone 544 C), respectively, while other states will have more flexible color mappings.

3. Code Implementation
Here’s how the code will look, broken down into key sections:

Step 1: HRV Calculation and Thresholds
We’ll calculate HRV based on the standard deviation of the RR intervals. This will give us a value that can be mapped to different emotional states.

Step 2: Color Transitions
We’ll ensure that stress (indigo) and relaxation (light blue) are mapped to accurate HRV values, while the other states (e.g., coral, amber, green) will be more flexible.

Key Parts of the Code:

Accurate HRV Calculation: The code calculates the average RR intervals and standard deviation to compute the HRV. This ensures accurate stress (low HRV) and relaxation (high HRV) detection.
Color Mapping:
  • Calm (Light Blue): HRV 60+ is mapped to calm, so the necklace will turn light blue.
  • Stress (Indigo): HRV below 30 represents stress, mapped to the indigo color.
  • Other Moods: HRV values in between are mapped to other emotional states (green, coral, yellow).
Touch Sensor Activation: The necklace activates the HRV measurement and feedback system only when the stone is touched, conserving power when it’s not in use.

Detailed plan

#include <Wire.h>
#include "MAX30105.h" // Heart rate sensor library
#include "Adafruit_MPR121.h" // Capacitive touch sensor library for stone interface

// Initialize sensors
MAX30105 particleSensor;
Adafruit_MPR121 capTouch = Adafruit_MPR121();

#define WHITE_PIN 3 // Pin for light blue (relaxation) color
#define BLUE_PIN 4 // Pin for indigo (stress) color
#define GREEN_PIN 5 // Pin for green (balance)
#define YELLOW_PIN 6 // Pin for yellow (nervous)
#define CORAL_PIN 7 // Pin for coral (alert)

int RRintervals[10]; // Array to store RR intervals
int rrIndex = 0; // Circular buffer index for RR intervals

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

  // Initialize the heart rate sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 sensor failed");
    while (1);
  }

  // Initialize the touch sensor
  if (!capTouch.begin(0x5A)) {
    Serial.println("MPR121 not found");
    while (1);
  }

  // Set up the color control pins
  pinMode(WHITE_PIN, OUTPUT); // Light blue for calm
  pinMode(BLUE_PIN, OUTPUT); // Indigo for stress
  pinMode(GREEN_PIN, OUTPUT); // Green for balance
  pinMode(YELLOW_PIN, OUTPUT); // Yellow for nervous
  pinMode(CORAL_PIN, OUTPUT); // Coral for alert

  // Start with all colors off
  digitalWrite(WHITE_PIN, LOW);
  digitalWrite(BLUE_PIN, LOW);
  digitalWrite(GREEN_PIN, LOW);
  digitalWrite(YELLOW_PIN, LOW);
  digitalWrite(CORAL_PIN, LOW);
}

void loop() {
  // Check for a touch on the stone
  if (capTouch.touched() & (1 << 0)) { // Detect touch on pin 0
    // Start measuring HRV when the stone is touched
    int heartRate = getHeartRate();
    int hrv = calculateHRV(heartRate);

    // Map HRV to colors
    if (hrv >= 60) {
      setFeedbackColor("light blue"); // Calm state
    } else if (hrv >= 50) {
      setFeedbackColor("green"); // Balanced state
    } else if (hrv >= 40) {
      setFeedbackColor("coral"); // Alert state
    } else if (hrv >= 30) {
      setFeedbackColor("yellow"); // Nervous state
    } else {
      setFeedbackColor("indigo"); // Stress state
    }
  }

  delay(1000); // Simple delay for polling
}

// Function to get heart rate from MAX30102
int getHeartRate() {
  long irValue = particleSensor.getIR(); // Get infrared value from sensor
  if (checkForBeat(irValue)) {
    long delta = millis() - previousMillis;
    previousMillis = millis();

    int beatsPerMinute = 60 / (delta / 1000.0);
    RRintervals[rrIndex] = delta;
    rrIndex = (rrIndex + 1) % 10; // Store RR intervals in circular buffer
    return beatsPerMinute;
  }
  return 0; // Return 0 if no beat detected
}

// Function to calculate HRV
int calculateHRV(int heartRate) {
  int sumRR = 0;
  int avgRR = 0;

  // Calculate average RR intervals
  for (int i = 0; i < 10; i++) {
    sumRR += RRintervals[i];
  }
  avgRR = sumRR / 10;

  // Calculate standard deviation of RR intervals as HRV
  int hrv = 0;
  for (int i = 0; i < 10; i++) {
    hrv += abs(RRintervals[i] - avgRR);
  }
  
  return hrv / 10; // Return average HRV
}

// Function to change the necklace color based on mood
void setFeedbackColor(String mood) {
  // Turn off all colors first
  digitalWrite(WHITE_PIN, LOW);
  digitalWrite(BLUE_PIN, LOW);
  digitalWrite(GREEN_PIN, LOW);
  digitalWrite(YELLOW_PIN, LOW);
  digitalWrite(CORAL_PIN, LOW);

  // Set the correct color based on HRV
  if (mood == "light blue") {
    digitalWrite(WHITE_PIN, HIGH); // Calm (relaxed) state
  } else if (mood == "indigo") {
    digitalWrite(BLUE_PIN, HIGH); // Stress state
  } else if (mood == "green") {
    digitalWrite(GREEN_PIN, HIGH); // Balanced state
  } else if (mood == "yellow") {
    digitalWrite(YELLOW_PIN, HIGH); // Nervous state
  } else if (mood == "coral") {
    digitalWrite(CORAL_PIN, HIGH); // Alert state
  }
}

draft code