Is this too big for ISR ?

Hi, I was wondering if this ISR is too much for processing power of Arduino?

The interrupt is set at 1kHz

ISR(TIMER1_COMPA_vect) {  //Interrupt at freq of 1kHz
  distance = getDistance(Lsensor); 
  pressure = getPressure(Psensor);
  prSwitch = getPswitch(Pswitch); 
  temp = getTemperature(tmp); 
  Fldtemp = getTemperature(Fluidtmp); 
  
  Serial.print(drive);
  Serial.print(" ");
  Serial.print(distance);
  Serial.print(" ");
  Serial.print(pressure);
  Serial.print(" ");
  Serial.print(prSwitch);
  Serial.print(" ");
  Serial.print(temp); 
  Serial.print(" ");
  Serial.println(Fldtemp);
}

And here are the function calls in the ISR:

int getPressure(const int pin) {
  float ADCpressure = analogRead(pin);
  ADCpressure = (ADCpressure/1023)*25;
  return (int) ADCpressure; 
}

int getPswitch(const int pin) {
  if(digitalRead(pin) == HIGH)
  { 
    return 1; 
  }
  if(digitalRead(pin) == LOW)
  { 
    return 0; 
  }
}

int getTemperature(const int pin) {
  float ADCtemperature = analogRead(pin);
  ADCtemperature = ADCtemperature/1.023;
  return (int) ADCtemperature; 
}

int getDistance(const int pin) {
  return analogRead(pin); 
}

Any ideas on how to make this work?

It's nothing to do with processing power. Don't do Serial.print inside an ISR.

http://www.gammon.com.au/interrupts

Just set a flag, test it in loop, and do your readings and displays there.

I need to send these data every millisecond to the PC.

Any help is appreciated

Thanks

At what baud rate?

I am using the max: 115200

Haven't you done the math yet?

115200 baud = 115200 bits per second = 11520 bytes per second = 11.5 bytes per millisecond

You can't send that many characters in the 1 mS time frame, it has nothing to do with the "processing power" of the Arduino, but the baud rate.

I am sorry i did not see the last reply you posted. Is there a way to increase the baud rate then. increase it in a way that PC can receive it?

You are getting close to the maximum. How about not sending the spaces? Even then you will be pushing it to condense your data into 11 bytes.

A more reasonable approach might be to do some calculations and send an average every second, or a delta (eg. rather than the temperature, the change in temperature).

You might have to send it as binary instead of characters. That way, for example, 0xFF saves on one character over 255.

How long do all your readings take? that might be more than a millisecond right there!

I managed to get 460800 baud with the uno. Above that, I would just see garbage.

You could also use Serial.write rather than print so you just print 2 bytes rather than somewhere between one and six (and you'd save another because you wouldn't need a deliminator). Then you'd have to write a program on your computer to interpret it, though

According to this: http://www.arduino.cc/en/Reference/AnalogRead

An analog read takes .1 mS, so your three Analog reads take 30% of your 1 mS anyway.

I optimized my analogRead to get the maximum speed out of it.
This page (near the bottom) shows you how to get 77 kHz reading speed out of analog read. So the analog read times is not a concern to me.

@WizenedEE
How did you manage to read that speed on the serial monitor of PC?

FardinB: @WizenedEE How did you manage to read that speed on the serial monitor of PC?

screen /dev/ttyACM0 460800

I run GNU/linux

How about this code for ISR? would it run faster?

ISR(TIMER1_COMPA_vect) {  //Interrupt at freq of 250Hz
  distance = getDistance(Lsensor); 
  pressure = getPressure(Psensor);
  prSwitch = getPswitch(Pswitch); 
  temp = getTemperature(tmp); 
  Fldtemp = getTemperature(Fluidtmp); 
  
  toprint = 0; //reset buffer 
  toprint += drive; 
  toprint += ' '; 
  toprint += distance;
  toprint += ' '; 
  toprint += pressure; 
  toprint += ' '; 
  toprint += prSwitch; 
  toprint += ' '; 
  toprint += temp; 
  toprint += ' '; 
  toprint += Fldtemp; 
  
  Serial.println(toprint); 
}

Are you using String? I wouldn't. And in any case you are still sending the same stuff.

 temp = getTemperature(tmp); 
  Fldtemp = getTemperature(Fluidtmp);

What device are you getting the temperature of, that changes 1000 times a second?

You can read the analog ports asynchronously.

http://www.gammon.com.au/interrupts

Scroll down to: "Read the Analog-to-Digital converter asynchronously"

I would separate the reading of sensors from communicating their values. i.e. use the ISR just to communicate the most recent sensor readings. Then do the reading of sensors somewhere else. Store the sensor values in some volatile globals and then use the ISR to slam out the most recent readings.

Either that or depending on how fast the data readings really change, only communicate the changes to the data vs the actual data. This could dramatically reduce the amount of data transfered.

But since you have not described the overall system and its real needs or what else might be going on in the foreground it is pretty difficult to make suggestions.

The big concern I have over using a serial port interface like this particularly at a high data rate is that there does not appear to be any sync sequence or checksum on the data. So if there is ever dropped character because of noise on the line, the two ends would be hopelessly out of sync with each other and the receiver would be "seeing" totally garbage information.

--- bill

@ Nick Gammon: Thank you for the info on your website. The temperature change of my system is like this: room temp to 100 deg C and back down to room temp in under 500 ms... as you can see I really need to capture and send this data.

@ bperrybap: I did what you suggested in other way around: readings in ISR and sending in the loop. I will definitely experiment with your suggestion.

Thank you

I think you are asking a bit much out of an Arduino. Something like this from NI might work better, and give you some margin: http://sine.ni.com/nips/cds/view/p/lang/en/nid/202596