2 Interrupts running at the same time

Hello,

I'm struggling with interrupts. My code is basicaly written to measure time between 2 falling edges and then based on that time i can calculate current power consumption. The problems starts when i try to measure time between falling edges on 2 pins at the same time, my code basicaly breaks and noone of measurments are correct.

#define SOLAR_POWER_GPIO      20
#define HOME_POWER_GPIO       21

#define IMPULSE_EDGE          FALLING

static void MEASURE_solar_power(void);
static void MEASURE_home_power(void);
void MEASURE_calculate();

static volatile float currentSolarPower = 0; 
static volatile float currentHomePower = 0;

static elapsedMillis solarPowerTimer;
static elapsedMillis homePowerTimer;

uint8_t next = 0;
uint8_t next2 = 0;

void setup()
{
  pinMode(SOLAR_POWER_GPIO, INPUT);
  pinMode(HOME_POWER_GPIO, INPUT);
  attachInterrupt(digitalPinToInterrupt(SOLAR_POWER_GPIO), MEASURE_solar_power, IMPULSE_EDGE);
  attachInterrupt(digitalPinToInterrupt(HOME_POWER_GPIO), MEASURE_home_power, IMPULSE_EDGE);
}

void loop()
{
  MEASURE_calculate();
}

void MEASURE_calculate()
{
  if (next == 2)
  {
    if (solarPowerTimer > 0)
    {
      currentSolarPower = 3600000.0f / (solarPowerTimer);
      Serial.print("Solar Power: ");
      Serial.println((int)currentSolarPower);
    }

    next = 0;
  }

  if (next2 == 2)
  {
    if (homePowerTimer > 0)
    {
      currentHomePower = 3600000.0f / (homePowerTimer);
      Serial.print("Home Power: ");
      Serial.println((int)currentHomePower);
    }

    next2 = 0;
  }
}

static void MEASURE_solar_power(void)
{
  if (next == 0)
  {
    solarPowerTimer = 0;
    next = 1;
  }
  else if (next == 1)
  {
    next = 2;
  }
}

static void MEASURE_home_power(void)
{
  if (next2 == 0)
  {
    homePowerTimer = 0;
    next2 = 1;
  }
  else if (next == 1)
  {
    next2 = 2;
  }
}

So if only one(no matter which one) interrupt handler is attached everything works just fine and measurements are correct but if both are attached code breaks and everything is wrong.

I'm running this on atmega2560 if that matters.

The quick, general answer, is that no code on an Arduino can run at the same time. Should be obvious.

Paul

Well they are not running exactly at the same time, interrupts cannot nest and they are assigned to different pins so in theory there is no corelation between them. By at the same time i meant that they both are turned on and they break code that is working separately. I jsut can't find what's really breaking it and how to prevent it

What is triggering the interrupt?

Interrupt is triggered by square wave generator for test purposes

uint8_t next = 0;
uint8_t next2 = 0;

These should be declare as volatile as they are changed in the interrupt.

There is a typo in this block

static void MEASURE_home_power(void)
{
  if (next2 == 0)
  {
    homePowerTimer = 0;
    next2 = 1;
  }
  //else if (next == 1) //typo
     else if (next2 == 1)
  {
    next2 = 2;
  }
}

After fixing a typo and declaring variables as volatile the problem still exists, it looks like these interrupts somewhow messes up with elapsedMillis and it's systick interrupt

looks like these interrupts somewhow messes up with elapsedMillis and it's systick interrupt

I'm not certain that the elapsedmillis class for the mega uses anything other than standard millis() under the hood.

There's certainly no need to use the library, and debugging your issues when using old school timing methods will be easier.

akimata:
After fixing a typo and declaring variables as volatile the problem still exists, it looks like these interrupts somewhow messes up with elapsedMillis and it's systick interrupt

Unlikely. If you look at the the applicable source code, you'll see it's just a wrapper for the standard millis()-based timing techniques. But, if in doubt, you can just implement those techniques yourself (per @cattledog).

Regardless, your code has other problems:

  • 'solarPowerTimer' and 'homePowerTimer' are accessed in both ISR and non-ISR code. Why didn't you make them volatile?

  • On the other hand, 'currentSolarPower' and 'currentHomePower' are only accessed in non-ISR code. Why DID you make them volatile?

  • Also accesses to 'solarPowerTimer' and 'homePowerTimer' are really accesses to 4-byte values. These will be non-atomic on an 8-bit AVR. When you access them in non-ISR code, you need to protect those accesses with Critical Sections.

akimata:
After fixing a typo and declaring variables as volatile the problem still exists,

Please always post the latest version of your program (in your next Reply) so we can see exactly what you changed.

...R