Problem with serial output

Hi All

I have a strange problem with my code, I hope you will be able to help me.

First some background about what my code is used for. It´s a very simple pice of code. It reads two analogue signals and send it via serial to a computer. Before it is send, each value will get a C or an M in front of the value, this is used in processing to identify the values which is received.

At one of the analogue inputs I measure the time between two inputs and calculate a beat pr minute. This is done by an interrupt, I just feed the analogue signal to the interrupt, which will trigger the measurement.

I have attached a image which shows how the signal I´m receiving looks like.

My problem is that I don´t receive the BPM and diffMillis output if I run the attached code, but if I disable the output from the two analogue interfaces I receive the BPM and diffMilis

This will work for the BPM and diffMillis:

  //Sending BPM and IBI if it´ ready
  if (BPMReady) {
    Serial.print("B");
    Serial.println(BPM); 
    Serial.print("Q");
    Serial.println(diffMillis);
    BPMReady = false;
  }
/* 
 //Sends values from the analogue inputs
  Serial.print("C");
  Serial.println(Slide_1_Value);  
  Serial.print("M");
  Serial.println(Slide_2_Value); 
*/

Are there any good explanation why I´m not able to receive the analogue output together with the BPM and diffMillis?

Here is my code:

#define PIN_Slide_1  A0
#define PIN_Slide_2  A1

int i;
int Slide_1_Value;
int Slide_2_Value;
boolean firstBeat, secondBeat, BPMReady;
float firstMillis, secondMillis, diffMillis,BPM;

void setup() {    
    Serial.begin(38400);
    attachInterrupt(0, CalcBPM, RISING);
}

void loop() {  
  i = 0;
  Slide_1_Value = 0;
  
  while (i < 4) { 
    Slide_1_Value = Slide_1_Value + analogRead(PIN_Slide_1);
    i++;    
  }
  Slide_1_Value = Slide_1_Value / 5;

  i = 0;
  Slide_2_Value = 0;

  while (i < 4) { 
    Slide_2_Value = Slide_2_Value + analogRead(PIN_Slide_2);
    i++;    
  }
  Slide_2_Value = Slide_2_Value / 5;    

  //Sending BPM and IBI if it´ ready
  if (BPMReady) {
    Serial.print("B");
    Serial.println(BPM); 
    Serial.print("Q");
    Serial.println(diffMillis);
    BPMReady = false;
  }
  //Sends values from the analogue inputs
  Serial.print("C");
  Serial.println(Slide_1_Value);  
  Serial.print("M");
  Serial.println(Slide_2_Value);  
}

void CalcBPM() {
  firstBeat = true;
  
  if(secondBeat){                        
    secondMillis = millis();
    diffMillis = secondMillis - firstMillis;
    
    BPM = 59999 / diffMillis;
    
    if (BPM > 240) 
      BPM = 0;
    
    BPMReady = true;
    secondBeat = false;                  
    firstBeat = false;
  }

  if(firstBeat){
    firstMillis = millis();
    firstBeat = false;
    secondBeat = true;
  }   
}

Snip20140610_1.png

Analog signals aren't normally used on digital inputs, the clue is the name.

For instance your interrupt routine may fire hundreds or thousands of times more than you want if the analog signal is noisy or if the input hysteresis of the chip isn't adequate.

The ATmega328 has a built in analog comparator which is precisely for doing this sort of analog level detection, the datasheet explains this.

I agree and will change it.

But that isn´t my problem. The measurement of the time between two period is working. I get the precise time between these period. I have verified this using a scope. The problem is that I don´t receive this time using the serial print command when I also have the analogue output send to the host. That´s my question, why don´t I get both the time difference between two period and the actual value from the analogue input?

Hi mwhansen

Just to clarify, therefore …

If you remove this from your program …

  //Sends values from the analogue inputs
  Serial.print("C");
  Serial.println(Slide_1_Value);  
  Serial.print("M");
  Serial.println(Slide_2_Value);

… then you DO see the output from this?

  if (BPMReady) {
    Serial.print("B");
    Serial.println(BPM); 
    Serial.print("Q");
    Serial.println(diffMillis);
    BPMReady = false;
  }

If you leave it in, you see the C and M print outputs, but not the B and Q?

Regards

Ray

float firstMillis, secondMillis, diffMillis,BPM;

Try changing to unsigned long to match the millis() function. You could get some problems due to precision of float, but mainly it will make the ISR quicker. And there could be some timing issues underlying your current problem.

The global variables which you use inside the ISR should be declared as volatile, I believe.

EDIT

Other useful guidance on ISRs here:

http://www.gammon.com.au/forum/?id=11488

Hi Ray

Correct. I will only receive C and M if this is enabled:

  //Sending BPM and IBI if it´ ready
  if (BPMReady) {
    Serial.print("B");
    Serial.println(BPM); 
    Serial.print("Q");
    Serial.println(diffMillis);
    BPMReady = false;
  }
  //Sends values from the analogue inputs
  Serial.print("C");
  Serial.println(Slide_1_Value);  
  Serial.print("M");
  Serial.println(Slide_2_Value);

But if I do:

  //Sending BPM and IBI if it´ ready
  if (BPMReady) {
    Serial.print("B");
    Serial.println(BPM); 
    Serial.print("Q");
    Serial.println(diffMillis);
    BPMReady = false;
  }
/*
  //Sends values from the analogue inputs
  Serial.print("C");
  Serial.println(Slide_1_Value);  
  Serial.print("M");
  Serial.println(Slide_2_Value);
*/

I will off cause not receive C and M but the correct B and Q values

I think I would take most of the code out of the ISR and just leave something like

void myISR() {
    curMicros = micros();
    newPulse = true;
}

and then process everything else in a function in the main body of code whenever it finds that newPulse is true.

...R