-
Notifications
You must be signed in to change notification settings - Fork 0
/
kontrool.ino
154 lines (130 loc) · 3.29 KB
/
kontrool.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* @file: kontrool.ino
*
* @date: 2021-06-02
*
* @author: Yazan Saleh & Lukas Güldenstein
*
* @brief: kontrool - controlling music with your body
*/
/* -------------------------------- includes -------------------------------- */
#include "ui.hpp"
#include "util.hpp"
#include "pulseSensor.hpp"
// debuggin?
#define DEBUG false
/* -------------------------- parameter definitons -------------------------- */
const unsigned long baudRate = 115200;
/* ----------------------------- pin definitions ---------------------------- */
const uint8_t muscleSensor = A0;
const uint8_t cvOut = 10;
const uint8_t pulsePin = A1;
const uint8_t motorPin = 3;
PulseSensor *PulseSensor::OurThis;
/* ---------------- global variables & object instantiations ---------------- */
UI ui = UI();
PulseSensor pulseSensor = PulseSensor(pulsePin);
const int numReadings = 31;
int readings[numReadings];
/* ---------------------------------- setup --------------------------------- */
void setup()
{
Serial.begin(baudRate);
if (!ui.start())
{
error("could not setup oled");
}
ui.displayLogo();
delay(2000);
ui.clearDisplay();
ui.drawTemplate();
pinMode(motorPin, OUTPUT);
// configure CV Pin with higher PWM freq
setHigherPWMFreq();
// threshhold to avoid noise
pulseSensor.setThreshold(480);
// zero readings array
for (int i = 0; i < numReadings; i++)
{
readings[i] = 0;
}
}
/* ------------------------- variables in interrupt ------------------------- */
volatile uint16_t muscleSenseVal = 0;
volatile uint8_t cvOutVal = 0;
/* ------------------------ global variables in loop ------------------------ */
unsigned long pTime = 0;
unsigned long pTime2 = 0;
unsigned long interval;
uint8_t average = 0;
int sum;
uint8_t count = 0;
int smooth;
int total = 0;
int readIndex = 0;
bool motorOn = false;
/* ---------------------------------- loop ---------------------------------- */
void loop()
{
unsigned long now = millis();
// smoothing
total -= readings[readIndex];
int bpm = pulseSensor.getBPM();
if (bpm < smooth + 5 || bpm > smooth - 5)
{
readings[readIndex] = bpm;
}
total += readings[readIndex];
readIndex += 1;
if (readIndex >= numReadings)
{
readIndex = 0;
}
// calculate smooth
smooth = total / numReadings;
/* -------------------------------- averaging ------------------------------- */
if (now - pTime2 >= 500)
{
pTime2 = now;
sum += smooth;
count++;
if (count >= 20)
{
average = sum / 20;
sum = 0;
count = 0;
}
}
// interval for the vibration motor output
interval = 30000 / smooth;
//
if ((now - pTime) >= interval)
{
pTime = now;
motorOn ^= true;
if (motorOn)
{
digitalWrite(motorPin, HIGH);
}
else
{
digitalWrite(motorPin, LOW);
}
}
// read pulse sensor value and map for display
int val = analogRead(A1);
val = map(val, 0, 1023, 0, 25);
// update ui
ui.update(muscleSenseVal, val, average);
analogWrite(cvOut, cvOutVal);
}
/* ------------------------ interrupt service routine ----------------------- */
// get data and process pulse samples
ISR(TIMER2_COMPA_vect)
{
DISABLE_PULSE_SENSOR_INTERRUPTS; // disable interrupts while we do this
PulseSensor::OurThis->onSampleTime();
muscleSenseVal = analogRead(muscleSensor);
cvOutVal = map(muscleSenseVal, 0, 1023, 0, 255);
ENABLE_PULSE_SENSOR_INTERRUPTS; // enable interrupts when you're done
}