This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Waking the nRF52840 from SYSTEMOFF - Arduino Nano 33 board

Hi,

I am fully aware that this is not an Arduino forum and that is not the responsibility of the users here to answer Arduino related questions - I have tried looking on the Arduino forums for answers but they basically send me to this forum as the question is quite specific to the nRF52840.

I am not a very experienced circuit board programmer and as such as I am having a hard time wrapping my head around how this all works. As such I am placing the full words next to abbreviations for other less experienced programmers. I would love if answers could do the same for me.

I am currently building a project using a nano 33 BLE. However, the issue that I am having should be irrelevant which board it is and as such I 'feel' like this forum is the correct place to pose my question, The project that I am building requires the Microcontroller (MCU) to stop consuming battery while it is not being used. The Nano 33 BLE comes with a 9 axis inertial measurement unit (IMU) which means that it includes an accelerometer, a gyroscope, and a magnetometer with 3-axis resolution each. As its name implies the communications chipset on the Nano 33 BLE can be both a BLE and Bluetooth client and host device.

I have managed to code, using the Arduino integrated development environment (IDE), my board to basically do what I want it to do. And I have even managed through the help of this forum to get it to go into SYSTEMOFF or 'deep sleep' mode when it is not emitting anything.

  // Enable sleep mode
  NRF_POWER->SYSTEMOFF = 1;

Gif showing very little power consumption on the nano 33 board

My problem is that I want to have the board come back to life in a smart way. Either through the press of a button, detection of movement from the accelerometer, I would even be very happy with it just sporadically waking up to check if it has changed position since last and if so run a check for possible centrals to connect to. I am really open to any suggestions or low hanging fruit here.

Press of a button

I have managed to make it reset using the button that the nano 33 BLE has integrated bu the problem here that if that button is pressed twice in succession it resets the board back to default, thus erasing the program. Seeing as this prototype will be used at a hospital for a few months during a feasibility study I can't really risk that happening.

Detecting Movement

This seems like it could be a problem as this would mean the IMU would need to be kept awake or woken up sporadically to check its movement. Using my multimeter I can see that running the IMU is a rather expensive experience when it comes to current draw. But perhaps there is a smart to do this that I am not seeing?

Sporadic checking

This is what I think would be the best way to do this, and was trying to look into using the watchdog timer to do so during a watchdog reset, alas I was informed correctly by that the reset behaviour informs us that the watchdog timer does not run during SYSTEMOFF as it does on the atmega328.

_____________

What the documentation says

I have read the documentation repeatedly, and as a bit of an amateur, I am simply lost trying to follow it, especially when I am trying to do so in an Arduino milieu. I am not entirely sure what is meant by the first 3 options from this section of the documentation:

"When in System OFF mode, the device can be woken up through one of the following signals:

  1. The DETECT signal, optionally generated by the GPIO peripheral.
  2. The ANADETECT signal, optionally generated by the LPCOMP module.
  3. The SENSE signal, optionally generated by the NFC module to wake-on-field.
  4. Detecting a valid USB voltage on the VBUS pin (VBUS,DETECT).
  5. A reset."

My guess' are as follows:

  1. I assume this is mapping a peripheral to a General Purpose Input/Output (GPIO) pin much like an external button? or another board?
  2. Using the Low power comparator to check the current voltage of a pin against a reference value?
  3. Some sort of signal that originated from a Near-field communication (NFC) detection?
  4. Plugging the device into a USB plug, much like plugging the Nano 33 BLE into my computer when uploading programs to it.
  5. Pressing the 'reset button' as I described earlier.

As you may see I am a bit at a loss here and would greatly appreciate a point in the right direction. Any sample code would be greatly appreciated, ideally in the Arduino IDE format but anything will do. Here is an example piece of code that I would like to wake up. If someone could provide some pseudocode it would go a long way to helping me out, and I presume many others working in the Arduino milieu.

#include <ArduinoBLE.h> // The BLE library

// BLE Rotation Service
BLEService rotationService("483a4000-fcde-4cc1-8ca1-59a33edf9061");

// BLE Accelerometer Characteristic :: BLERead allows central devices to read data.
//                                     BLEWrite allows centrals to write to this peripheral.
//                                     BLENotify allows remote clients to get notifications if this characteristic changes.
BLECharacteristic rotationChar("483a4001-fcde-4cc1-8ca1-59a33edf9061", BLERead | BLEWrite | BLENotify, 17, true);

void blePeripheralConnectHandler(BLEDevice central) 
{
  _connected = true;
}

void blePeripheralDisconnectHandler(BLEDevice central)
{
  _connected = false;
}

void Sleep()
{
  digitalWrite(LED_PWR, LOW); // turn off power LED
  digitalWrite(PIN_ENABLE_I2C_PULLUP, LOW); // turn off I²C pullup
  digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW); // turn sensor OFF

  delay(500);

  // Enable sleep mode
  NRF_POWER->SYSTEMOFF = 1;
}

void setup() {

  // begin initialization
  if (!BLE.begin()) {
    while (1);
  } 

  // Setup characteristic and the service to emit as well as their respective names
  BLE.setLocalName("SYNCS123456");
  BLE.setDeviceName("SYNCS123456");
  BLE.setAdvertisedService(rotationService);
  rotationService.addCharacteristic(rotationChar);
  BLE.addService(rotationService);
  rotationChar.writeValue(rotation);

  // assign event handlers for connected, disconnected to peripheral These are called when connecting or disconnecting from the central
  BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

  // start advertising
  BLE.advertise();
}

void loop() 
{
  if(_connected)
  {
    // Do something (for example turn on IMU and start transmitting data)  
  }
  else()
  {
    // Run a timer that after x time calls the Sleep() function.
  }
}

Thank you very much for any help that can be provided on this and know that I have really tried over the last few weeks to get this answered on Arduino but they pish me here, I feel like I'm falling right between the two and thus kinda lost =(

regards!

  • Hi,

    Have you seen that Arduino has their own BLE library? This may be an easier way to start for you if you are already familiar with the Arduino enviroment than writing to the registers directly... 

    Maybe they have included some power management options in their BLE library? Take a look at https://www.arduino.cc/en/Reference/ArduinoBLE

    If not using the Arduino library, I recommend using our nRF5 SDK and looking at the Power Management Example, which is located under \examples\peripheral\pwr_mgmt in the SDK install folder.

    There are two options for achieving low energy. They are SYSTEM OFF mode and SYSTEM ON IDLE mode. You should choose based on how long it will take until your next wake up.

    When using SYSTEM OFF the device will start in reset state, so you will need to run the start up code again which will draw some current. If you haven't plan to sleep for long then it may not pay off to use SYSTEM OFF.

    For SYSTEM ON idle only the CPU goes to sleep, in WFE (wait for event) state.  You can wake up from system ON idle with any internal or external event, the RTC is typically used for this.

    From SYSTEM OFF you need an external wake up source, which could be a button press, a sense signal from NFC, or you can sample an analog value with the comparator and wake up after passing a certain threshold.

    If you enable the sense mechanism of any GPIO pin (SENSE bit in PIN_CNF[n] register), a DETECT signal will be generated if the correct sense is detected. Using our nRF5 SDK you can configure the sense field of a pin using function:

    nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config)

    About the reset button: the external button is connected to P0.18 RESETN so I recommend using another pin as GPIO for a wake up button. I am not sure why your program gets erased pressing the reset button twice, could it be that it sets the arduino board in bootloader mode? What happens if you press the reset button again? See this thread in the Arduino forums: https://forum.arduino.cc/index.php?topic=630864.0

    If you are planning to make a possible commercial product I will recommend bypassing the Arduino enviroment and using our nRF5 SDK directly instead.

    Best regards,

    Marjeris

Related