Problem with attachInterrupt() not calling a function properly

Hello all,

So I am attempting to interrupt my sketch (which is only printing a message to the serial monitor over and over) to run a function to minimize two signals I am inputting. When executing nothing was happening so I inserted a message in the function I was calling “null_coils” to print to the serial monitor and the sketch interrupts itself, but the program stops completely and only prints the first character of the message I am attempting to print to the serial monitor. I tested the interrupts itself with a test function I wrote that just prints a couple messages to the serial monitor just to see if it was set up correctly and the test function was called just fine (it interrupted the sketch and printed the messages properly). It is when I call the ‘null_coils’ function where I am getting the problem where only the first character of the message being printed is being printed to the serial monitor, which leads me to believe the function is not being run properly.

Here is my code:

//Sets up interrupt pin so that when the switch is flipped the auto-nulling process
//begins. The interrupt as used now doesn't seem to be able to interrupt itself 
  pinMode(interruptPin, INPUT_PULLUP);

//where the interrupting function is utilized with pin 'interruptPin' connected to a physical switch 
//should call function 'null_coils' but not stepping through function properly
//Only prints first character of message in 'null_coils' to serial monitor and then stops completely
  attachInterrupt(digitalPinToInterrupt(interruptPin), null_coils , CHANGE);
  SPI.usingInterrupt(interruptPin);
}

void loop()
{
  Serial.println(" Change switch to begin auto-nulling ");

}

//This is the test function I called to see if interrupts was set up correctly
//When called from attachInterrupt() it worked just as expected and was set up correctly
void test()
{
  Serial.println(" To see if interrupts works ");
  Serial.println(" I wrote this code ");
  Serial.println(" Just to check if it calls ");
  Serial.println(" a function properly ");
}

/////////////////////////////////////////////////////////////////////////////////////
//This will be the function that holds the nulling algorithm and is called when the
//interrupt switched is flipped. Logic is 1-high, 0-low, dp-digipot, fg-function gen
// pin_control_1  pin_control_2   x_out   z_out
//    1               1              dp     fg
//    1               0              fg     dp
//    0               1              dp     dp
//    0               0              dp     dp
 
void null_coils()  //The function the interrupts should be calling
{
  Serial.println("Nulling Coils"); //Prints only the first character 'N'

 
  int x_values[1048576]; //An array to store the x signal values

//Filling the x signal array with the appropriate values
  for(int float_counter=0; float_counter<1023; float_counter++) 
  {
    for(int x_counter=0; x_counter<1023; x_counter++)
    {
      x_values[x_counter*1024 + float_counter] = x_matrix(slsPin_x,xz_signal_sampling_Pin,x_counter);
    }
  }

  int z_values[1048576]; //An array to store the z signal values

 
//Filling the z signal array with the appropriate values
  for(int float_counter=0; float_counter<1023; float_counter++)
  {
    for(int z_counter=0; z_counter<1023; z_counter++)
    {
      z_values[z_counter*1024 + float_counter] = z_matrix(slsPin_z,xz_signal_sampling_Pin,z_counter);
    }
  }

////////////////////////////////////////////////////////////////////////////  
//Need to fix to do element wise addition of these huge array pointers
//Not quite relevant for this code is not utilized and will be deleted
  int values[1048576];
    for(int counter= 0; counter<1048576; counter++)
  {
    
    values[counter] = x_values[counter] + z_values[counter];
    
  }
////////////////////////////////////////////////////////////////////////////  
  int minimum_position_x; //minimum position of x value
  int minimum_x=1023; //minimum value of x signal

 //stepping through x signal
  for(int counter=0; counter<1048576; counter++)
  {
    if(x_values[counter] < minimum_x)
    {
      minimum_x = x_values[counter];
      minimum_position_x = counter;
    }
  }

int minimum_position_z; //minimum position of z value
int minimum_z = 1023; //minimum value of z signal

//stepping through z signal
  for(int counter=0; counter<1048576; counter++)
  {
    minimum_z = z_values[counter];
    minimum_position_z = counter;
  }
  int minimum_position;
  int minimum = 1023;

////////////////////////////////////////////////////////////////////////////  
//This needs to find the minimum value and its x,z position. This means that
//we need to find a way to convert the position in the array back into the
//matrix coordinates. 
//This code will also be deleted as it is not utilized
  for(int min_counter= 0; min_counter<1048576; min_counter++)
  {
    
    if(values[min_counter]<minimum)
    {
      minimum = values[min_counter];
      minimum_position = min_counter;
    }

    
  }

////////////////////////////////////////////////////////////////////////////  


///////////////////////////////////////////////////////////////////////////
//This will be where we write the positions of the x,z min to the actual digipot
//and thus will end the program.
//Write minimum x and z to digiPots
digiPotWrite(slsPin_x, 1, minimum_x);
digiPotWrite(slsPin_z, 1, minimum_z);
}

  int x_values[1048576]; //An array to store the x signal valuesThis array uses over 2 million bytes. Which Arduino board are you using, I wonder ?

I am using the Arduino Atmega2560

I am using attempting to use the Arduino Atmega2560

Where does all the extra RAM come from?

UKHeliBob:

  int x_values[1048576]; //An array to store the x signal values

This array uses over 2 million bytes. Which Arduino board are you using, I wonder ?

 int x_values[1048576]; //An array to store the x signal values
  int z_values[1048576]; //An array to store the z signal values
  int values[1048576];

AND THERE'S 3 OF THEM!!!

What in the name of the Flying Spaghetti Monster are you trying to do that need 3 million integers?!?!

2560 only has 8 Kbyte SRAM, limiting you to 4096 ints. And the sketch needs some of that to use for other variables, etc.

I am using the massive amount of integers to minimize two signals (x and z) that are connected to a current supply to null a magnetic field. Do I just not have enough RAM?

You do not. Not even close.

I have modified my code to store 2048 integers instead of 3 million and I continue to have the same problem. Does anyone have any suggestions?

Does anyone have any suggestions?

Post the code.
All of it.

Here is most of the sketch I had a 9000 characters issue so I deleted the parts that were irrelevant

#include <SPI.h>
#include <math.h>
#include <MatrixMath.h>

//These three pins are the x,float,z digipot slave select pins.
int slsPin_x=48;
//The float pin is used to control the offset of the sine wave. What I mean by this is that if you have nulled z and know the z value, the digipot value for z will get 
//written to the float digipot. That way the sine wave will be added to the voltage from the float digipot which is the same as the z digipot. This mirrors the process
//used by the regular current supplies where the signal is added to the channel voltage at the offset.
int slsPin_float=46;
int slsPin_z=44;
//These pins are used to control whether the function generator or digipot signals are
// sent to the x,y driver coils. Logic is 1-high, 0-low, dp-digipot, fg-function gen
// pin_control_1  pin_control_2   x_out   z_out
//    1               1              dp     fg
//    1               0              fg     dp
//    0               1              dp     dp
//    0               0              dp     dp
int pin_control_1 = 22;
int pin_control_2 = 24;

//Specifies the interrupt pin that the switch is attached so that the user can initiate
int interruptPin = 3;

//Specifies the pin that the x or z signal will be read from using samplesignal func.
//Assumptions about the frequency and signal size are made in by this function.
int xz_signal_sampling_Pin = 15;

// Used in the null coils to be the digipotvalue that describes the z_min and x_min 
//int x_min_position;
//must declare constraining variable and "set equal to" constrain function for the sketch to compile
int x_min_position = constrain(x_min_position, 0, 1023);
int z_min_position = constrain(z_min_position, 0, 1023);


/////////////////////////////////////////////////////////////////////////////////////
void setup()
{
  // sets slave select pin as output
  pinMode(slsPin_x, OUTPUT);
  pinMode(slsPin_float, OUTPUT);
  pinMode(slsPin_z, OUTPUT);
  
  //makes sure slave selct pin is initially high
  digitalWrite(slsPin_x, HIGH);
  digitalWrite(slsPin_float, HIGH);
  digitalWrite(slsPin_z, HIGH);
  
//This defines the initial state for the controls with logic as in my notebook
  pinMode(pin_control_1, OUTPUT);
  digitalWrite(pin_control_1, LOW);
  pinMode(pin_control_2, OUTPUT);
  digitalWrite(pin_control_2, LOW);
  
//SPI specificatons as required by the AD5293
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  Serial.begin(9600);

//Sets up interrupt pin so that when the switch is flipped the auto-nulling process
//begins. The interrupt as used now doesn't seem to be able to interrupt itself 
  pinMode(interruptPin, INPUT_PULLUP);

//where the interrupting function is utilized with pin 'interruptPin' connected to a physical switch 
//should call function 'null_coils' but not stepping through function properly
//Only prints first character of message in 'null_coils' to serial monitor and then stops completely
  attachInterrupt(digitalPinToInterrupt(interruptPin), null_coils , CHANGE);
  SPI.usingInterrupt(interruptPin);
}

void loop()
{
  Serial.println(" Change switch to begin auto-nulling ");
  
}

//This is the test function I called to see if interrupts was set up correctly
//When called from attachInterrupt() it worked just as expected and was set up correctly
void test()
{
  Serial.println(" To see if interrupts works ");
  Serial.println(" I wrote this code ");
  Serial.println(" Just to check if it calls ");
  Serial.println(" a function properly ");
}

/////////////////////////////////////////////////////////////////////////////////////
//This will be the function that holds the nulling algorithm and is called when the
//interrupt switched is flipped. Logic is 1-high, 0-low, dp-digipot, fg-function gen
// pin_control_1  pin_control_2   x_out   z_out
//    1               1              dp     fg
//    1               0              fg     dp
//    0               1              dp     dp
//    0               0              dp     dp
 
void null_coils()  //The function the interrupts should be calling
{
  Serial.println("Nulling Coils"); //Prints only the first character 'N'

 
  int x_values[1024]; //An array to store the x signal values

//Filling the x signal array with the appropriate values
  for(int float_counter=0; float_counter<32; float_counter++) 
  {
    for(int x_counter=0; x_counter<32; x_counter++)
    {
      x_values[x_counter*32 + float_counter] = x_matrix(slsPin_x,xz_signal_sampling_Pin,x_counter);
    }
  }

  int z_values[1024]; //An array to store the z signal values

 
//Filling the z signal array with the appropriate values
  for(int float_counter=0; float_counter<32; float_counter++)
  {
    for(int z_counter=0; z_counter<32; z_counter++)
    {
      z_values[z_counter*32 + float_counter] = z_matrix(slsPin_z,xz_signal_sampling_Pin,z_counter);
    }
  }

////////////////////////////////////////////////////////////////////////////  
//Need to fix to do element wise addition of these huge array pointers
//Not quite relevant for this code is not utilized and will be deleted
 
////////////////////////////////////////////////////////////////////////////  
  int minimum_position_x; //minimum position of x value
  int minimum_x=1023; //minimum value of x signal

 //stepping through x signal
  for(int counter=0; counter<1048576; counter++)
  {
    if(x_values[counter] < minimum_x)
    {
      minimum_x = x_values[counter];
      minimum_position_x = counter;
    }
  }

int minimum_position_z; //minimum position of z value
int minimum_z = 1023; //minimum value of z signal

//stepping through z signal
  for(int counter=0; counter<1048576; counter++)
  {
    minimum_z = z_values[counter];
    minimum_position_z = counter;
  }
  int minimum_position;
  int minimum = 1023;

////////////////////////////////////////////////////////////////////////////  
//This needs to find the minimum value and its x,z position. This means that
//we need to find a way to convert the position in the array back into the
//matrix coordinates. 
//This code will also be deleted as it is not utilized
  

////////////////////////////////////////////////////////////////////////////  


///////////////////////////////////////////////////////////////////////////
//This will be where we write the positions of the x,z min to the actual digipot
//and thus will end the program.
//Write minimum x and z to digiPots
digiPotWrite(slsPin_x, 1, minimum_x);
digiPotWrite(slsPin_z, 1, minimum_z);
}
////////////////////////////////////////////////////////////////////////////  
int x_matrix(int slspin, int sampling_pin, int counter)
{
    int x_sample;

    digitalWrite(pin_control_1, HIGH);
    digitalWrite(pin_control_2, HIGH);

    digiPotWrite(slspin, 1, counter);
    x_sample = sampleSignal(sampling_pin);

    digitalWrite(pin_control_1, LOW);
    digitalWrite(pin_control_2, LOW);
    return x_sample;
}

int z_matrix(int slspin, int sampling_pin, int counter)
{
  int z_sample;

  digitalWrite(pin_control_1, HIGH);
  digitalWrite(pin_control_2, HIGH);

  digiPotWrite(slspin, 1, counter);
  z_sample = sampleSignal(sampling_pin);

  digitalWrite(pin_control_1, LOW);
  digitalWrite(pin_control_2, LOW);
  return z_sample;
}

Nulls123:
I am using the massive amount of integers to minimize two signals (x and z) that are connected to a current supply to null a magnetic field. Do I just not have enough RAM?

You see the picture a posted with a tractor and a tanker wedged under a bridge that’s too small for them?

You’re 1,000x worse than that right now.

And I’ll be honest, I read that first sentence and I still don’t know what you are trying to do. Is it some niche kind of scientific measurement of something?

From what I can tell of that code, you don’t even need to store all that crap in the arrays. You aren’t performing any detailed calculation on it, and I don’t see where you need the position values either. Just process the stuff as it comes in.

int16_t min_x = INT16_MAX;
int16_t min_z = INT16_MAX;
//int16_t min_sum = INT16_MAX;

  for(int float_counter=0; float_counter<1023; float_counter++)
  {
    for(int x_counter=0; x_counter<1023; x_counter++)
    {
      int16_t x_temp = x_matrix(...);
      int16_t z_temp = z_matrix(...);

      min_x = min(min_x, x_temp);
      min_z = min(min_z, z_temp);
      //min_sum = min(min_sum, z_temp+x_temp);
    }
  }

digiPotWrite(slsPin_x, 1, min_x);
digiPotWrite(slsPin_z, 1, min_z);

Is there a reason this won’t work?

for(int counter=0; counter<1048576; counter++)
  {
    if(x_values[counter] < minimum_x)

I thought you said you’d changed it?

My mistake I missed two number both for loops now iterate 1024 times for the whole x and z array (still doesn't work). And yes for the scientific measurements I am working on I have to first null any external magnetic fields (which is what this should do). I don't think there is a reason that approach wouldn't work I will try to modifying my code, Thank you so much! I may also try modulating my signal with a square wave instead of minimizing. Thank you all for helping!

interrupt my sketch (which is only printing a message to the serial monitor over and over) to run a function to minimize two signals I am inputting. When executing nothing was happening so I inserted a message in the function I was calling "null_coils" to print to the serial monitor and the sketch interrupts itself, but the program stops completely and only prints the first character of the message I am attempting to print to the serial monitor.

Up through at least v1.6.9, Serial.xxx was not callable from inside interrupt service routines, and would behave exactly as you describe if non-interrupt code was also printing. This is because the serial code needed its own interrupt to empty the buffer that Serial.write()/etc is filling, and if interrupts were disabled due to being in the service routine for some other interrupt, this would never happen. I heard a rumor that the most recent code includes a "fix" for this.

Not that you don't have other problems...

If that function is being called inside your ISR, it will cause problems because it takes too much time to execute. ISRs must run fast. They should put some stuff in volatile variables and then quit.