External interrupt RAK11720 in while loop

Hello!

Iam using the RAK11720 and i want to use an external interrupt. But i have a problem that the interrupt is not running asynchronously while the code is running in a while loop as below

attachInterrupt(MainswitchInput, HandleMainSwitch, RISING);


volatile bool interruptOccurred = false; // Define a volatile flag to indicate interrupt occurrence

void HandleMainSwitch()
{
    Conf.Mainswitch = !Conf.Mainswitch ;		// Invert from low to high and high to low
     
    interruptOccurred = true;
    Serial.print("Mainswitch state");
    Serial.println(Conf.Mainswitch);
    
    save_at_setting(RWStateMainSwitch);
}

void manageSinglePumpSystem() {

  interruptOccurred = false;
 while(!Serial.available() > 0 || Conf.Mainswitch == 1){
    Serial.println(Conf.Mainswitch);
    Pump1_Management();
    
  
  if(Serial.available() > 0 || Conf.Mainswitch == 0 ){
    Serial.println(Conf.Mainswitch);
    interruptOccurred = false;
    break;
    
  }
 }
}

in the manageSinglePumpSystem() function i want to check if there is an interrupt of an external pin and then i want to step out of the while loop. But for some reason the code is running stock in the while loop and the interrupt is not working.

Are there some options to make this work?

Kind regards,
Marnick

How is Conf.Mainswitch defined? Is it volatile as well?
Is Conf.Mainswitch changed in the Pump1_Management() function?

What is Serial.println(Conf.Mainswitch); printing? Is Conf.Mainswitch ever changing?

Why don’t you use the interruptOccurred flag itself to end the while loop?

void manageSinglePumpSystem()
{
	while ((!Serial.available() > 0) || (Conf.Mainswitch == 1))
	{
		Serial.println(Conf.Mainswitch);
		Pump1_Management();

		if ((Serial.available() > 0) || (Conf.Mainswitch == 0))
		{
			Serial.println(Conf.Mainswitch);
			interruptOccurred = false;
			break;

		}
		if (interruptOccured)
		{
			interruptOccurred = false;
			break;
		}
	}
}

hello @beegee

How is Conf.Mainswitch defined? Is it volatile as well?
Conf.Mainswitch is defined as volatile byte.

Is Conf.Mainswitch changed in the Pump1_Management() function?
no its not changed in the Pump1_Management() function. its only changing in te HandleMainSwitch() when an interrupt occurs.

What is Serial.println(Conf.Mainswitch); printing? Is Conf.Mainswitch ever changing?
When an interrupt occurs the Conf.Mainswitch is toggling like this
Conf.Mainswitch = !Conf.Mainswitch ;

Then its printing its value to check which state it is.

Why don’t you use the interruptOccurred flag itself to end the while loop?
I tried this before but the flag is not changing because the interrupt is not executing while its inside the “while” loop → while(!Serial.available() > 0 || Conf.Mainswitch == 1){

but if the interrupt works then i can use the `interruptOccurred to end the while loop.
So the point is, inside the while loop the interrupt is not calling, but outside the while loop the interrupt is working.

Kind regards,
Marnick

I just realise, your while is looping without any delays.
Did you try to put a delay(100) into the while loop?

With the delay(100) its working! but there is another problem, its not allowed to use delays in the code because the code needs to run constantly… Is there another way to do this?

No, your while loop is blocking everything else without the delay.

Why is a delay of 100ms critical for your application?

From your code it looks like you are taking action when
(a) Conf.Mainswitch is changing
(b) something or nothing (don’t really understand what you are doing there) is available on the serial port

If that happens faster than in 100ms, you need another strategy.

If at some point you need to send data over LoRaWAN or LoRa P2P or BLE, this while loop will interfere with the transmission as well.

Well iam using it for a pump system to read the voltage and ampere values realtime and these are flucturating based on the solar panel. Based on different voltages and amperes i controll the pumps ( on/off ) so its neccesary that i dont have a lot of delay time.

The serial port is checking if a configuration tool is connected. When i connect a configuration tool it needs to stop the while loop, otherwise i cant change parameters.

Hello @beegee,

Is there a way to use millis() instead of delay()?

i tried the following with millis() but the interrupt is only working with a delay().


void manageSinglePumpSystem() {
    unsigned long previousMillis = 0;
    const long interval = 100;  // Interval in milliseconds

    // Main loop
    while (Conf.Mainswitch == 1) {
        unsigned long currentMillis = millis();

        // Check if Serial data is available or Mainswitch is turned off
        if (Serial.available() > 0 || Conf.Mainswitch == 0) {
            Serial.println("System Off");
            break;
        }

        // Check if it's time to manage the pump
        if (currentMillis - previousMillis >= interval) {
            previousMillis = currentMillis;  // Save the last time we managed the pump
            Serial.println("System On");
            // Perform pump management
            Pump1_Management();
           
        }
    }
}

Do you have ideas for this?

Millis() does not help here.
As I said, your while() loop is blocking the MCU.
I have no other solution for you.

@beegee , Thankyou very much for your help! Is there by the way a brownout interrupt available in the api or something like this? I want to save values to the flash memory if the main voltage crosses a certain voltage. Or is this only possible with creating my own “brownout” interrupt with a ADC measurement to check its voltage?

The API does not provide a function to detect low supply voltage. You will have to create it by yourself.