xxxxxxxxxx
// Pace Visualizer Dashboard for OpenProcessing
// This code simulates the visualization of running pace data
// and how it would connect with Arduino hardware
let paceHistory = []; // Array to store pace data
let heartRateHistory = []; // Array to store heart rate data
let targetPace = 5.5; // Target pace in minutes per kilometer
let currentPace = 5.5; // Current pace in minutes per kilometer
let currentHeartRate = 140; // Current heart rate in BPM
let ledColor = [0, 255, 0]; // Current LED color (RGB)
let motorVibrating = false; // Vibration motor state
// Zone thresholds
const SLOW_THRESHOLD = 0.3; // 0.3 mins/km slower than target
const FAST_THRESHOLD = 0.3; // 0.3 mins/km faster than target
// Colors for different zones
const COLORS = {
SLOW: [0, 0, 255], // Blue for slower than target
TARGET: [0, 255, 0], // Green for at target
FAST: [255, 165, 0], // Orange for faster than target
TOO_FAST: [255, 0, 0] // Red for too fast
};
function setup() {
createCanvas(800, 600);
textFont('Arial');
// Generate sample pace and heart rate history
generateSampleData();
// Create simulate button
let simulateButton = createButton('Simulate Real-Time Data');
simulateButton.position(650, 20);
simulateButton.mousePressed(simulateNewData);
}
function draw() {
background(20);
// Draw title
fill(255);
textSize(24);
textAlign(CENTER);
text('Pace Visualizer Dashboard', width/2, 40);
// Draw LED strip visualization
drawLEDStrip();
// Draw pace graph
drawPaceGraph();
// Draw heart rate graph
drawHeartRateGraph();
// Draw current stats
drawCurrentStats();
// Draw vibration motor status
drawVibrationStatus();
}
function drawLEDStrip() {
// Draw LED strip simulation
fill(50);
rect(50, 80, 700, 50, 10);
// Draw 10 LED lights
for (let i = 0; i < 10; i++) {
fill(ledColor[0], ledColor[1], ledColor[2]);
ellipse(100 + i * 70, 105, 30, 30);
}
fill(255);
textSize(16);
textAlign(LEFT);
text('LED Strip Simulation:', 50, 70);
}
function drawPaceGraph() {
fill(255);
textSize(16);
textAlign(LEFT);
text('Pace History (min/km):', 50, 160);
// Draw graph background
fill(40);
rect(50, 170, 700, 120, 5);
// Draw target pace line
stroke(200, 200, 0);
strokeWeight(1);
let targetY = map(targetPace, 4, 7, 290, 170);
line(50, targetY, 750, targetY);
// Label target pace
noStroke();
fill(200, 200, 0);
textAlign(RIGHT);
text(targetPace.toFixed(1), 45, targetY + 5);
// Draw pace zone thresholds
stroke(100);
strokeWeight(1);
let slowY = map(targetPace + SLOW_THRESHOLD, 4, 7, 290, 170);
let fastY = map(targetPace - FAST_THRESHOLD, 4, 7, 290, 170);
line(50, slowY, 750, slowY);
line(50, fastY, 750, fastY);
// Draw pace history
noFill();
strokeWeight(3);
beginShape();
for (let i = 0; i < paceHistory.length; i++) {
let x = map(i, 0, paceHistory.length - 1, 50, 750);
let y = map(paceHistory[i], 4, 7, 290, 170);
// Color code pace points
if (paceHistory[i] > targetPace + SLOW_THRESHOLD) {
stroke(COLORS.SLOW[0], COLORS.SLOW[1], COLORS.SLOW[2]);
} else if (paceHistory[i] < targetPace - FAST_THRESHOLD) {
stroke(COLORS.FAST[0], COLORS.FAST[1], COLORS.FAST[2]);
} else {
stroke(COLORS.TARGET[0], COLORS.TARGET[1], COLORS.TARGET[2]);
}
vertex(x, y);
ellipse(x, y, 5, 5);
}
endShape();
// Add labels to graph
noStroke();
fill(255);
textAlign(RIGHT);
text("4:00", 45, 170);
text("5:30", 45, 230);
text("7:00", 45, 290);
}
function drawHeartRateGraph() {
fill(255);
textSize(16);
textAlign(LEFT);
text('Heart Rate History (BPM):', 50, 320);
// Draw graph background
fill(40);
rect(50, 330, 700, 120, 5);
// Draw heart rate zones
noStroke();
fill(50, 50, 80);
rect(50, 330, 700, 30); // Zone 5
fill(50, 50, 100);
rect(50, 360, 700, 30); // Zone 4
fill(50, 70, 50);
rect(50, 390, 700, 30); // Zone 3
fill(70, 70, 50);
rect(50, 420, 700, 30); // Zone 2
fill(80, 50, 50);
rect(50, 450, 700, 20); // Zone 1
// Add zone labels
textAlign(RIGHT);
fill(255);
text("190", 45, 330);
text("170", 45, 360);
text("150", 45, 390);
text("130", 45, 420);
text("110", 45, 450);
text("90", 45, 470);
// Draw heart rate history
stroke(255, 100, 100);
strokeWeight(2);
noFill();
beginShape();
for (let i = 0; i < heartRateHistory.length; i++) {
let x = map(i, 0, heartRateHistory.length - 1, 50, 750);
let y = map(heartRateHistory[i], 90, 190, 470, 330);
vertex(x, y);
}
endShape();
}
function drawCurrentStats() {
// Draw current stats panel
fill(40);
rect(50, 480, 340, 100, 5);
fill(255);
textSize(16);
textAlign(LEFT);
// Current pace
text('Current Pace:', 70, 510);
textSize(24);
fill(ledColor[0], ledColor[1], ledColor[2]);
text(currentPace.toFixed(2) + ' min/km', 200, 510);
// Current heart rate
textSize(16);
fill(255);
text('Heart Rate:', 70, 550);
textSize(24);
fill(255, 100, 100);
text(currentHeartRate + ' BPM', 200, 550);
}
function drawVibrationStatus() {
// Draw vibration motor status panel
fill(40);
rect(410, 480, 340, 100, 5);
fill(255);
textSize(16);
textAlign(LEFT);
text('Vibration Motor Status:', 430, 510);
// Circle to represent motor
if (motorVibrating) {
fill(255, 100, 100);
ellipse(480, 540, 30, 30);
text('Active - Adjust Pace', 500, 550);
} else {
fill(100, 100, 100);
ellipse(480, 540, 30, 30);
text('Inactive - On Target', 500, 550);
}
}
function generateSampleData() {
// Generate sample data for visualization
for (let i = 0; i < 100; i++) {
// Create realistic pace fluctuations around target
let noise = sin(i * 0.05) * 0.5 + random(-0.2, 0.2);
let pace = targetPace + noise;
paceHistory.push(pace);
// Create heart rate data that correlates with pace
let hrNoise = sin(i * 0.08) * 10 + random(-5, 5);
let hr = 140 + (targetPace - pace) * 20 + hrNoise;
heartRateHistory.push(constrain(hr, 90, 190));
}
// Set current values to the last values
currentPace = paceHistory[paceHistory.length - 1];
currentHeartRate = heartRateHistory[heartRateHistory.length - 1];
updateLEDColor();
}
function simulateNewData() {
// Add new data point to simulate real-time data
let newPaceNoise = random(-0.3, 0.3);
let newPace = currentPace + newPaceNoise;
if (newPace < 4) newPace = 4;
if (newPace > 7) newPace = 7;
currentPace = newPace;
paceHistory.push(newPace);
// Adjust heart rate based on pace
let hrChange = (targetPace - newPace) * 10 + random(-5, 5);
currentHeartRate = constrain(currentHeartRate + hrChange, 90, 190);
heartRateHistory.push(currentHeartRate);
// Remove oldest data point if too many
if (paceHistory.length > 100) {
paceHistory.shift();
heartRateHistory.shift();
}
// Update LED color based on new pace
updateLEDColor();
}
function updateLEDColor() {
// Determine LED color based on current pace compared to target
if (currentPace > targetPace + SLOW_THRESHOLD * 2) {
// Way too slow - bright blue
ledColor = [0, 0, 255];
motorVibrating = true;
} else if (currentPace > targetPace + SLOW_THRESHOLD) {
// Too slow - blue
ledColor = COLORS.SLOW;
motorVibrating = true;
} else if (currentPace < targetPace - FAST_THRESHOLD * 2) {
// Way too fast - bright red
ledColor = COLORS.TOO_FAST;
motorVibrating = true;
} else if (currentPace < targetPace - FAST_THRESHOLD) {
// Too fast - orange
ledColor = COLORS.FAST;
motorVibrating = true;
} else {
// Just right - green
ledColor = COLORS.TARGET;
motorVibrating = false;
}
}