How to use interruptions

The most common use of interruptions in Waspmote is to mix them with low power consumption states. The repeating procedure shall be:

  • Step 1: Enable the interruption you want to listen to

  • Step 2: Set a low-power consumption states and wait an interruption to wake up Waspmote up from this state

  • Step 3: Interruption event happens

  • Step 4: Disable interruptions

  • Step 5: Check the interruption flags in order to know the interruption source which generated the alarm

  • Step 6: Do normal operation (measuring and sending information)

  • Step 7: Clear interruption flags

  • Step 8: Clear the interruption pin to increase the code robustness

Enable interruptions

Keep in mind that there are two basic steps involved when enabling interruptions:

  • Enable the microcontroller pin to generate interruptions (RXD1 and/or TXD1 pin)

  • Set up the interruption source to generate the interruption signal

Enable the interruption pin

There is a general function enableInterrupts() which modifies intConf to add a new active interruption related to a specific module. Besides, the interruption pin (RXD1 or TXD1) is enabled to generate interruptions attaching the corresponding subroutine to this event.

When enabling an interruption for a module, other modules are capable of interrupting the microcontroller through the same interruption pin.

Example of use

{
 // Enables the specified interruption
 enableInterrupts(ACC_INT);
}

Set up the interruption source

Each module has its own way to set up interruptions. Normally, the API functions that enable the interruption sources also enable the corresponding microcontroller interruption pin (RXD1 or TXD1) so usually it is not necessary to call enableInterrupts() function.

The best way to understand each setting is to read more about them in the specific chapter dedicated for each module in this document.

Set low-power consumption states

When entering a low-power consumption state, some peripherals are switched off by default:

  • Both microcontroller's UARTs are closed

  • SOCKET1 power supply is switched off

  • RTC is powered down to its backup battery pin in order to maintain the interruption and date info

  • I2C bus is unset

  • SD card is switched off

Besides, the low-power consumption functions in the API permit to select what power supplies of Waspmote are switched off. On the contrary, it is possible to leave some of these supplies powered on if the user is interested on it. The SOCKET0 power supply and sensor board power supply can be selected to remain powered on. This is useful to use sleep modes or set up sensor interruptions, respectively.

The input arguments for the low-power consumption state are:

ALL_OFF: SOCKET0 and sensor board are switched off SENSOR_ON: Remain sensor power supply SOCKET0_ON: Remain SOCKET0 power supply ALL_ON: SOCKET0 and sensor power supplies are not switched off. They are kept as they are.

There are several modes to set low-power consumption states mixed with external interruptions:

  • sleep mode

  • sleep mode with Watchdog interruption

  • deep sleep mode with RTC interruption

  • sleepAgr mode (when using Agriculture Board)

Sleep

In this state, Waspmote only expects external interruptions, so the user must keep in mind to set up them to be able to wake up the microcontroller.

The sleep options are specified as input:

Examples of use

{
 // case 1: switch off all power supplies
 PWR.sleep(ALL_OFF);
 // case 2: sensor board power supply remains on
 PWR.sleep(SENSOR_ON);
 // case 3: SOCKET0 power supply remains on
 PWR.sleep(SOCKET0_ON);
 // case 4: Both SOCKET0 and sensor power supply remain on
 PWR.sleep(ALL_ON);
}

Sleep with Watchdog interruption

In this mode, Waspmote expects external interruptions. Besides, the Watchdog interruption is always enabled to ensure the microcontroller wakes up after the specified time if any other interruption arrives. Possible interval values from 16ms to 8s:

WTD_16MS WTD_32MS WTD_64MS WTD_128MS WTD_250MS WTD_500MS WTD_1S WTD_2S WTD_4S WTD_8S

The sleep options are also specified as input:

Example of use

{
 // Set sleep mode:
 // 1. Enabling Watchdog interruption to be generated after 32ms
 // 2. All modules are switched off
 PWR.sleep(WTD_32MS, ALL_OFF);
}

Deep Sleep

In this mode, Waspmote expects external interruptions. Besides, the RTC interruption is always enabled to ensure the microcontroller wakes up if no interruption arrives. The RTC alarm is set as specified in the RTC Programming Guide.

The sleep options are also specified as input:

Example of use

{
 // Set deep sleep mode:
 // 1. Enabling RTC interruption to be generated after 10 seconds from now
 // 2. All modules are switched off
 PWR.deepSleep(00:00:00:10, RTC_OFFSET, RTC_ALM1_MODE2, ALL_OFF);
 // Set deep sleep mode:
 // 1. Enabling RTC interruption to be generated at 17:00 on day 15th
 // 2. All modules are switched off
 PWR.deepSleep(15:17:00:00, RTC_ABSOLUTE, RTC_ALM1_MODE2, ALL_OFF);
}

Agriculture Board Sleep mode

The Agriculture board uses its self low-power consumption mode because there are some digital pins which need to be disabled.

{
 // Set Agriculture sleep mode:
 // 1. Enabling RTC interruption to be generated after 30 seconds from now
 // 2. Sensor board power supply remains on
 Agriculture.sleepAgr("00:00:00:30", RTC_OFFSET, RTC_ALM1_MODE3, SENSOR_ON );
 // Set Agriculture sleep mode:
 // 1. Enabling both RTC and pluviometer interruption
 // 2. Sensor board power supply remains on
 Agriculture.sleepAgr("00:00:00:30", RTC_OFFSET, RTC_ALM1_MODE3, SENSOR_ON, SENS_AGR_PLUVIOMETER);
}

Interruptions with no low-consumption statesleep mode

It is possible to set up interruptions with no sleep mode in Waspmote by simply avoiding this step. During the execution, when the interruption arrives, the microcontroller enters the corresponding subroutine and marks the interruption flags. So, the user's program should poll intFlag so as to check if there are pending interruptions to be treated.

It is important to remark that when listening to interruptions, it is not possible to communicate via UART1 because there would be interferences in the interruption line. This means it is not possible to use SOCKET1, nor GPS nor auxiliaryauxiliar sockets.

Interruption events execute subroutines

A subroutine is a function called when an interruption occurs in order to treat the interruption event. Waspmote API has been designed not to do any long-term operation inside the subroutines, but to mark the corresponding flag associated to the interruption event.

Two subroutines defined in Winterruptions.c are associated to the interruption pins when the interruptions are enabled:

  • onHAIwakeUP (On High Active Interruption). This subroutine is run by the modules which generate rising-edge interruptions (usually in RXD1 pin).

  • onLAIwakeUP (On Low Active Interruption). This subroutine is run by the modules which generate falling-edge interruptions (usually in TXD1 pin).

These subroutines check both intConf flag and monitoring pin related to each interruption source in order to know what module triggered the interruption. When the two conditions match:

  • intFlag is marked on the correct position to show the module that provoked the interruption.

  • intCounter is incremented each time an interruption is detected.

  • intArray is incremented in the correct position to know how many times a module has activated the interruption.

Initially no further action is taken, in an attempt to add the minimum time delay possible in the execution trace of the program’s main code. Once these flags are updated, the microcontroller returns to the last executed instruction before capturing the interruption.

It is in the main code where the interruption must be treated by the user when the interruption flag is marked in intFlag vector. The aim of this design is to avoid pausing actions that Waspmote may be doing at the moment the interruption triggers, an example would be sending a packet through the XBee radio.

Disable interruptions

Similarly to the interruption enabling functions, keep in mind that there are two basic steps involved in disabling interruptions:

  • Disable the microcontroller pin not to generate interruptions (RXD1 and/or TXD1 pin)

  • Disable the interruption source not to generate any interruption signal in the interruption/UART pins

Disable the interruption pin

There is a general function disableInterrupts() which modifies intConf to remove enabled interruptions related to specific modules. Besides, the interruption pin (RXD1 or TXD1) is disabled to avoid generating interruptions in that pin.

When disabling an interruption for a module, also interruptions are disabled for the rest of the modules which share the same interruption pin but intConf keeps configured for those other modules.

Example of use

{
 // Disables the specified interruption
 disableInterrupts(ACC_INT);
 }

Disable the interruption source

Each module has its own way to disable interruptions. The best way to understand it is to read more about them in the specific chapter dedicated for each module in this document.

Check the interruption flags

As explained before, there are several flags which are updated inside the interruption subroutines which permit to know if an interruption has happened and which of the modules has triggered it.

After an interruption occurs the user must analyze the contents of intFlag in order to know the interruption source. The API defines some constants related to each interruption source inside intFlag:

#define ACC_INT 1 // bit 0 #define RTC_INT 2 // bit 1 #define WTD_INT 4 // bit 2 #define SENS_INT 8 // bit 3 #define PLV_INT 16 // bit 4 #define HIB_INT 32 // bit 5 #define RAD_INT 64 // bit 6 #define XBEE_INT 128 // bit 7 #define PIR_3G_INT 256 // bit 8

Thus, the following comparison allows the user to distinguish between different events:

{
 if (intFlag & ACC_INT)
 {
 // Accelerometer interruption treatment
 }
 if (intFlag & RTC_INT)
 {
 // RTC interruption treatment
 }
 if (intFlag & WTD_INT)
 {
 // Watchdog interruption treatment
 }
 // etc...
}

Clear the interruption flags

After checking the interruption source of the event, it is mandatory to clear the 'intFlag' variable. If not, the captured interruption is not cleared and the next checking will determine that the same interruption was provoked again.

The following function clears the global flag ‘intFlag’. It sets 'intFlag' to zero.

Example of use

{
 clearIntFlag(); // Clears ‘intFlag’
 }

Clear the interruption pin

At the end of the process, it is recommended to use the following function in order to clean the interruption pins (which are shared with the UART1). This will help to increase the robustness of your codes because it permits to avoid interferences in this line between different interruption sources and communication via UART1.

Example of use

{
 PWR.clearInterruptionPin();
 }

Basic example

This is a basic example based on accelerometer interruptions. It is possible to see all the steps previously explained in order to use the interruptions in Waspmote. In this example, a sleep mode is used switching off all modules.

void loop()
{
  ACC.ON();
  USB.println(F("\r\nAccelerometer ON"));
  ACC.setMode(ACC_LOW_POWER_5);
  ACC.setFF();
  USB.println("Free Fall interrupt configured");
  USB.println(F("Accelerometer mode: ACC_LOW_POWER_5"));

  // Sleep to Wake activation
  ACC.setSleepToWake();
  USB.println("Sleep to Wake mode configured");
  
  PWR.sleep(ALL_OFF);
   
  if( intFlag & ACC_INT )
  {
    // unset the Sleep to Wake
    ACC.unSetSleepToWake();
    // clear the accelerometer interrupt flag on the general interrupt vector
    intFlag &= ~(ACC_INT);
    // read the acceleration source register
    delay(200);
    USB.ON();
    USB.println(F("++++++++++++++++++++++++++++++++++"));
    USB.println(F("++ Free Fall interrupt detected ++"));
    USB.println(F("++++++++++++++++++++++++++++++++++"));    
  }
  delay(2000);
}

Last updated