Hello everyone, I have an Arduino Nano with the old bootloader (ATmega328P), and I'm encountering an issue when attempting to print data to the serial monitor. Specifically, while it does display the rate, there are instances where it sends data at random intervals. Could you please assist me with resolving this issue?
You'll have to post your code so folks can take a look. Please don't forget to use code tags.
Ok. Here is the code
int pulsePin = A0; // Define pulse sensor pin
int blinkPin = 13; // Define LED indicator pin
volatile int BPM; // Variable to store heart rate (beats per minute)
volatile int Signal; // Variable to store raw analog signal from pulse sensor
volatile int IBI = 600; // Initial value for time interval between beats
volatile boolean Pulse = false; // Flag to indicate pulse detection
volatile boolean QS = false; // Flag to indicate Quantified Self event
static boolean serialVisual = true; // Flag to enable ASCII visual representation
volatile int rate[10]; // Array to store last ten IBI values
volatile unsigned long sampleCounter = 0; // Counter to track time
volatile unsigned long lastBeatTime = 0; // Time of last beat
volatile int P = 512; // Peak value of pulse waveform
volatile int T = 512; // Trough value of pulse waveform
volatile int thresh = 525; // Threshold to find instant of heart beat
volatile int amp = 100; // Amplitude of pulse waveform
volatile boolean firstBeat = true; // Flag to indicate first beat
volatile boolean secondBeat = false; // Flag to indicate second beat
void setup() {
pinMode(blinkPin, OUTPUT); // Set LED pin as output
Serial.begin(57600); // Set baud rate to 57600 for serial communication
interruptSetup(); // Setup interrupt for pulse sensor
}
void loop() {
serialOutput(); // Output data to serial monitor
if (QS == true) { // If heart beat detected
serialOutputWhenBeatHappens(); // Output heart beat data
QS = false; // Reset Quantified Self flag
}
delay(20); // Delay for stability
}
void interruptSetup() {
TCCR2A = 0x02; // Configure Timer2 for CTC mode
TCCR2B = 0x06; // Set prescaler to 256
OCR2A = 0X7C; // Set top value for 500Hz sample rate
TIMSK2 = 0x02; // Enable interrupt on match between Timer2 and OCR2A
sei(); // Enable global interrupts
}
void serialOutput() {
if (serialVisual == true) { // If ASCII visual representation enabled
arduinoSerialMonitorVisual('-', Signal); // Output visual representation
} else {
sendDataToSerial('S', Signal); // Otherwise, send raw data
}
}
void serialOutputWhenBeatHappens() {
if (serialVisual == true) { // If ASCII visual representation enabled
Serial.print(" Heart-Beat Found "); // Print heart beat message
Serial.print("BPM: "); // Print heart rate label
Serial.println(BPM); // Print heart rate value
} else {
sendDataToSerial('B', BPM); // Otherwise, send heart rate data
sendDataToSerial('Q', IBI); // Also, send time between beats data
}
}
void arduinoSerialMonitorVisual(char symbol, int data) {
const int sensorMin = 0; // Minimum sensor value
const int sensorMax = 1024; // Maximum sensor value
int sensorReading = data; // Current sensor reading
int range = map(sensorReading, sensorMin, sensorMax, 0, 11); // Map sensor reading to range of 0-11
// Further actions based on mapped range can be implemented here
}
void sendDataToSerial(char symbol, int data) {
Serial.print(symbol); // Send symbol prefix
Serial.println(data); // Send data value
}
ISR(TIMER2_COMPA_vect) { // Interrupt service routine for Timer2
cli(); // Disable interrupts
Signal = analogRead(pulsePin); // Read analog signal from pulse sensor
sampleCounter += 2; // Increment sample counter
int N = sampleCounter - lastBeatTime; // Calculate time since last beat
// Check for peak and trough of pulse waveform
if (Signal < thresh && N > (IBI / 5) * 3) {
if (Signal < T) {
T = Signal; // Update trough value
}
}
if (Signal > thresh && Signal > P) {
P = Signal; // Update peak value
}
// Look for heartbeat signal surge
if (N > 250) {
if ((Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3)) {
Pulse = true; // Set pulse detection flag
digitalWrite(blinkPin, HIGH); // Turn on LED indicator
IBI = sampleCounter - lastBeatTime; // Calculate time interval between beats
lastBeatTime = sampleCounter; // Update time of last beat
if (secondBeat) {
secondBeat = false; // Clear secondBeat flag
for (int i = 0; i <= 9; i++) {
rate[i] = IBI; // Seed running total with latest IBI value
}
}
if (firstBeat) {
firstBeat = false; // Clear firstBeat flag
secondBeat = true; // Set secondBeat flag
sei(); // Enable interrupts
return; // Exit ISR
}
word runningTotal = 0; // Variable to hold running total of last 10 IBI values
// Shift data in rate array and add up 9 oldest IBI values
for (int i = 0; i <= 8; i++) {
rate[i] = rate[i + 1]; // Shift data
runningTotal += rate[i]; // Add up values
}
rate[9] = IBI; // Add latest IBI value
runningTotal += rate[9]; // Add latest IBI value to runningTotal
runningTotal /= 10; // Calculate average of last 10 IBI values
BPM = 60000 / runningTotal; // Calculate heart rate
QS = true; // Set Quantified Self flag
}
}
// Check for heartbeat signal decline
if (Signal < thresh && Pulse == true) {
digitalWrite(blinkPin, LOW); // Turn off LED indicator
Pulse = false
I think maybe you've got too much going on in the ISR. I was under the impression that ISRs had to be very quick, set a flag and do all the other stuff in the main loop.
Maybe someone else who is more expert than me can weigh in on how much you can get away with in an ISR, though.
2 Likes
Now I can not recieve data xd
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.