working an ISR

I want to use an interrupt to recalculate a value that is created during setup. I know how to call the interrupt. I'm just a little confused because you can't return and you can't take any arguments to the function called by the interrupt. So:

  1. If I have a global variable that goes into the main loop, will it automatically change in the main loop if the interrupt function assigns a new value?

  2. Can I call another function while I am in the ISR?

  3. From what I understand the ISR will function in the background, so if I'm running the loop and it operates in a certain way based on this value. Will the loop continue execution through while the ISR is operating?

  1. yes, but make sure you declare it "volatile". Be very careful how you access it, if it is a dataype longer than a single byte.
  2. yes, but make it quick
  3. no, there is only one thread of execution.
  1. no, there is only one thread of execution.

But, the code will resume right where it was interrupted when the ISR ends.

Thanks guys, I think it will be ok on timing, it's literally 3 calculations.

As a follow up question, can I ask, what do I do if my volatile values are floating point numbers? I know how we all despise floats for their hideous inaccuracy, but I'm basically stuck working with them for one important function.

The problem arises because the float is four bytes long, and the natural word size is a single byte.
You could be in the middle of accessing the variable in your background when the interrupt occurs, causing part of the value to change.
Protect your accesses in background (loop) with disable/enable interrupts.

Floating point maths in interrupt context may not be optimal - would fixed-point do the trick?

Can you explain why you need to use an IRQ to recalculate the formula (whatever)?
maybe there are alternative solutions.

AWOL - The value being recalculated could be a fixed point number, all the floats are only to four decimal places precision anyway. I was not aware that fixed point was a native data type in the Arduino IDE. Do you think I should multiply everything by 10^4 to remove the decimal, declare the values as int, and then just static cast and divide down when I need the values as a float? please keep in mind that in my code below, the value that I get 'delayTime' from is an itsy bitsy floating point decimal that is returned to the program from a subroutine during setup, then I multiply up to get 4 sig-figs and cast it to unsigned long.

robtillart - basically the main loop is a pulse chain that pulses to 3 output pins, twice each, in a specific order. There is a delay time before the sequence begins. I need to sometimes modify that delay time depending on what is happening with the system. What I'd like is to be able to have an interrupt that will break out every now and again and see if there is a new number waiting in the serial port. if so, it should recalculate, if not it should immediately get back into the program before the next period. Even if those calculations make the program skip one cycle, thats ok, as long as by the next they pulse chain is on again and set to a new delay.

void loop(){
  last = current;
  current = digitalRead(7);

  while ((current != HIGH && last != LOW) || (current != HIGH && last != HIGH) || (current != LOW && last != LOW)){
   //basically states the three conditions that we are not allowed to move on from
   //first says if current state is low and the last state is high we are at a fall, check again.
   //second says if both are low we are in a low state, check again.
   //third says if both are high we are in a high state, check again.
   //the only condition on which we leave the loop is the fourth possible state:
   //the current state is high and the last one was low
   //indicating that we are seeing a rise time, so we exit
   last = current;
   current = digitalRead(7);
   }
    //this delay is to set the ON/OFF chain at a specific delay from the rise time detected on pin 7
    timeCheck = micros();
    while((micros() - timeCheck) < delayTime){
      
    }
    //these delays and on times are meant to cumulatively equal the duration of the period, which is approx ~ .016667 seconds, 60hz cycle
    //the 1000 mSec delays are there to slow the program down for visual confirmation that the firing sequence is phase coherent
    digitalWrite(10, HIGH);
    delayMicroseconds(1389); 
    //delay(1000);
    digitalWrite(10, LOW);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(9, HIGH);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(9, LOW);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(6, HIGH);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(6, LOW);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(10, HIGH);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(10, LOW);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(9, HIGH);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(9, LOW);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(6, HIGH);
    delayMicroseconds(1389);
    //delay(1000);
    digitalWrite(6, LOW);
    //at this point the program goes back to the while loop to make sure it's delaying after the next rise
    //keep in mind that all of these commands execute in slightly less than one period
    //therefore when we return to the while loop we should be in a low state and have a few microseconds before the next rise
}

I was not aware that fixed point was a native data type in the Arduino IDE

Well, apart from the obvious 8.0 format, neither was I.

Floating point maths in interrupt context may not be optimal - would fixed-point do the trick?

I don't think I understand what you are trying to tell me here.

I'm trying to tell you that fixed-point arithmetic may be faster than floating-point arithmetic.
However, since I don't know what arithmetic you are doing (hint), I can't say for sure.

lol!
Assume these are some likely values that you'd see for an alpha value, in radians.
{ 3.1070, 3.1086, 3.1102, 3.1117, 3.1133, 3.1149, 3.1165, 3.1180, 3.1196, 3.1212, 3.1227, 3.1243, 3.1259, 3.1275, 3.1290, 3.1306, 3.1322, 3.1337, 3.1353, 3.1369,
3.1385, PI }

void alphaFind( float &qInternal, float &alphaRadians,  float &qCalculated){
  for (int i = 0; i < alphaPosSize; i++){  //generate values of q to find alpha

    float thisAlpha = pgm_read_float(alphaPos+i);
    //Serial.print("thisAlpha = "); Serial.println(thisAlpha, 9);

    float q = (((V * V)/(pi*w0*L)))*(2*pi - 2*thisAlpha + sin(2*thisAlpha));

    if ( q <= (1 + qInternal) && q >= (qInternal - 1)){
      //assign q
      alphaRadians = thisAlpha; //assign alpha
      qCalculated = q;
      Serial.print("the calculated level of Q internal is: ");
      Serial.println(q, 9);
     // delay(3000);
      break;

    }
  }
}//end alphaFind

But that's not your ISR, it's got serial prints in it.
What are you doing in your ISR?

righto, sorry. they look very similar:

void findNewAlpha(){
  
   for (int i = 0; i < alphaPosSize; i++){  //generate values of q to find alpha

    float thisAlpha = pgm_read_float(alphaPos+i);

    float q = (((V * V)/(PI*w0*L)))*(2*PI - 2*thisAlpha + sin(2*thisAlpha));

    if ( q <= (1 + qInternal) && q >= (qInternal - 1)){
      //assign q
      
      qCalculated = q;
      microAlphaSeconds = 1000000 * thisAlpha * ((1 / (float(frequency)) / (2 * PI)));
      delayTime = (unsigned long) microAlphaSeconds;
      break;

    }
  }
}

which assumes that qInternal is different from that last function I posted.