Author Topic: Use a Pulse sensor with DigiX -- Due compatibility issue ?  (Read 4083 times)

Ian

  • Newbie
  • *
  • Posts: 1
Use a Pulse sensor with DigiX -- Due compatibility issue ?
« on: March 22, 2014, 06:52:22 pm »
Hi,
I am trying to use a Pulse sensor (http://pulsesensor.myshopify.com/) with my digiX. The following code is supposed to be DUE compatible, but it crashes the digiX as soon as it is loaded. Would someone have any clue of what is wrong with that code ?
Thanks

source: http://pulsesensor.proboards.com/thread/216/pulsesensor-arduino-due-3v-compatibility

PulseSensorAmped_Arduino_1dot1.ino
Code: [Select]
int TCPin = 53; // any free pin on Arduino Due, used to trigger interrupts (can be disconnected)
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13; // pin to blink led at each beat
int fadePin = 5; // pin to do fancy classy fading blink at each beat
int fadeRate = 0; // used to fade LED on with PWM on fadePin

// these variables are volatile because they are used during the interrupt service routine!
volatile int BPM; // used to hold the pulse rate
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // holds the time between beats, the Inter-Beat Interval
volatile boolean Pulse = false; // true when pulse wave is high, false when it's low
volatile boolean QS = false; // becomes true when Arduoino finds a beat.

void setup() {
  Serial.begin(115200); // we agree to talk fast!
  Serial.println("setup--1");
  pinMode(blinkPin, OUTPUT); // pin that will blink to your heartbeat!
  pinMode(fadePin, OUTPUT); // pin that will fade to your heartbeat!
  interruptSetup(); // sets up to read Pulse Sensor signal every 1mS
  Serial.println("setup--2");
}

void loop() {

  attachInterrupt(TCPin, takePulse, HIGH);
  interrupts(); // enable interrupts when youre done!

  sendDataToProcessing('S', Signal); // send Processing the raw Pulse Sensor data
  if (QS == true) { // Quantified Self flag is true when arduino finds a heartbeat
    fadeRate = 255; // Set 'fadeRate' Variable to 255 to fade LED with pulse
    sendDataToProcessing('B', BPM); // send heart rate with a 'B' prefix
    sendDataToProcessing('Q', IBI); // send time between beats with a 'Q' prefix
    QS = false; // reset the Quantified Self flag for next time
  }

  ledFadeToBeat();

  delayMicroseconds(20000); // take a break
}

void ledFadeToBeat() {
  fadeRate -= 15; // set LED fade value
  fadeRate = constrain(fadeRate, 0, 255); // keep LED fade value from going into negative numbers!
  analogWrite(fadePin, fadeRate); // fade LED
}

void sendDataToProcessing(char symbol, int data ) {
  Serial.print(symbol); // symbol prefix tells Processing what type of data is coming
  Serial.println(data); // the data to send culminating in a carriage return
}

Interrupt.ino
Code: [Select]
volatile int rate[10]; // used to hold last ten IBI values
volatile unsigned long sampleCounter = 0; // used to determine pulse timing
volatile unsigned long lastBeatTime = 0; // used to find the inter beat interval
volatile int P = 2048; // used to find peak in pulse wave (Arduino Due)
volatile int T = 2048; // used to find trough in pulse wave (Arduino Due)
volatile int thresh = 2048; // used to find instant moment of heart beat (Arduino Due)
volatile int amp = 100; // used to hold amplitude of pulse waveform
volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean TCPulse; //Due clock timer pulse value

// This function to configure a Timer was given some replies above, I changed only the used CLOCK.
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk((uint32_t)irq);
  TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
  uint32_t rc = VARIANT_MCK / 128 / frequency; //128 because we selected TIMER_CLOCK4 above
  TC_SetRA(tc, channel, rc / 2); //50% high, 50% low
  TC_SetRC(tc, channel, rc);
  TC_Start(tc, channel);
  tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS;
  tc->TC_CHANNEL[channel].TC_IDR = ~TC_IER_CPCS;
  NVIC_EnableIRQ(irq);
}

void TC3_Handler()
{
  TC_GetStatus(TC1, 0);
  digitalWrite(TCPin, TCPulse = !TCPulse);
}

void interruptSetup() {
  // Initializes TC3 to throw an interrupt every 1mS.

  // Start timer. Parameters are:

  // TC1 : timer counter. Can be TC0, TC1 or TC2
  // 0 : channel. Can be 0, 1 or 2
  // TC3_IRQn: irq number. See table.
  // 40 : frequency (in Hz)
  // The interrupt service routine is TC3_Handler. See table.
  startTimer(TC1, 0, TC3_IRQn, 1000); //last argument is clock speed (Hz), so 1000Hz clock time = 1ms
}




// THIS IS THE TC3 INTERRUPT SERVICE ROUTINE.
// TC3 makes sure that we take a reading every 1 miliseconds
void takePulse() { // triggered every timer pulse
  noInterrupts(); // disable interrupts while we do this
  analogReadResolution(12); // 12-bit read resolution for Arduino Due
  Signal = analogRead(pulsePin); // read the Pulse Sensor

// ...
// I understand that the analog signal processing should not be relevant in the present thread
// Full code: http://pulsesensor.proboards.com/thread/216/pulsesensor-arduino-due-3v-compatibility#ixzz2wkIa4DR7
// ...

}


gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Use a Pulse sensor with DigiX -- Due compatibility issue ?
« Reply #1 on: March 23, 2014, 04:43:27 am »
The code looks like  a very quick and dirty solution. When I see, that a function like takePulse() disables interrupts without re-enabling them its ugly.  When you need to disable interrupts, you have to re-enable them, as soon as possible.

You are enabling however interrupts in the main loop(), where you attaching the ISR in EACH !!! loop!

attachInterrupt(..) is something, which needs to go in the setup() block, if there are no very special reasons, that you attach and detach different ISR depending on your programs status.

It looks for me, that you have found a very partial piece of a program from early development state.

The third result in google brought me this link, when I searched for the possible origin of your code fragments: https://github.com/wilbefast/mechanic-human-beings/tree/master/PulseSensorAmped_Arduino_1dot1

That seems to be the original avr based code, which was used as base for your code.  Try to organize your code similar.  All ISR related stuff needs to go to setup.  disabling and enabling of interrupts should always be symmetric and as close to that code position, which needs it.