Go Down

Topic: Interrupt LowPower Mode using an IMU (Read 194 times) previous topic - next topic

Deamerbeamer

Hello, I would appreciate your help in the following matter:

Currently I am using an arduino nano to run and process data from an IMU ("MiniIMU-9 v5", runs with the LSM6 library). The goal is to include an SD-Card adapter to store the data from the sensor colleceted during several days. The IMU will be attached to a box to see how much it was moved in a predefined period of time.

I already got everything running in a first version, where the IMU-data is saved the entire time, leading to high energy consumption and large amount of data. The idea to improve the system is to enable the lowpower-mode on the microcontroller (using the LowPower library) and to start saving the acceleration data once the system is moved using interrupts.

My problem is that I don't get any information from the serial monitor using the following code, so I would be happy if you could help me solve this problem. Of course I would also be happy to hear any other advices on how to build that kind of system.

The SLC-pin of the IMU is connected to the D2-pin of my Arduno Nano because I want to use the analog signal to wake the microcontroller up and to display the data on the serial monitor.


Code: [Select]

#include <Wire.h>
#include <LSM6.h>
#include <LowPower.h>

LSM6 imu;

char report[80];

void setup()
{
  Serial.begin(9600);

  Wire.begin();

  if (!imu.init())
  {
    Serial.println("Failed to detect and initialize IMU!");
    while (1);
  }
  imu.enableDefault();
    attachInterrupt(0, pin2Interrupt, LOW);
}

void loop()
{

  LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
}

void pin2Interrupt()
{
   imu.read();
   snprintf(report, sizeof(report), "A: %6d %6d %6d    G: %6d %6d %6d",
    imu.a.x, imu.a.y, imu.a.z,
    imu.g.x, imu.g.y, imu.g.z);
  Serial.println(report);
  delay(100);
}

PaulS

You can NOT use delay() in an interrupt service routine.

All those words describing the IMU are worthless. A link to the IMU would be very useful.

Typically, LOW as the trigger for the interrupt is wrong. You want the interrupt to happen on the rising edge, the falling edge, or either edge.
The art of getting good answers lies in asking good questions.

Deamerbeamer

Thank you for your response.

Is there any other possibility to enable serial communication during the interrupt service routine?
Here's the link for the used IMU: https://www.pololu.com/product/2738/specs

Also thank you for the advice concerning the trigger.

Have you ever used an analogue signal for an interrupt service?

PaulS

Quote
Have you ever used an analogue signal for an interrupt service?
That the voltage can vary has no effect on triggering an interrupt. Any voltage above 60% of the reference voltage is HIGH. Any value below 60% is LOW.

The ONLY thing you should be doing in the ISR is noting that it happened. If the ISR is triggered at all, the Arduino will wake up and resume executing the statement after the one that bored it to tears (I mean that put it to sleep).

Since you don't have any code after that, loop() runs again, and you go right back to sleep.

You need to learn what you can, and what you can NOT do in an ISR, and don't do the things you can't.
The art of getting good answers lies in asking good questions.

Deamerbeamer

Again thank you for your help.

What I want it to do, is to sleep the entire time if the acceleration signal does not exceed a specific value.

Quote
Any value below 60% is LOW.
Would that mean that I need to check if the acceleration is above a specific limit?

Let's assume that I want the controller the following thing to do:

1. If the sensor rests, the system is put to sleep and LED 13 is put LOW
2. if the sensor is moved, LED 13 is put HIGH
3. if the sensor rests, resume to state 1.

That would mean:

- loop() contains the command to put everything to sleep for an undefined period of time, also setting LED 13 LOW
- attachInterrupt(0,wake,RISING) calls a function "wake" that wakes the system once the input of 0 is rising
- as soon as the RISING state is finished, everything retuns to sleep by continuing loop()

I am sorry for my poor understanding of how these things work, however I really want to get into it and I don't see the mistake in the way of thinking yet. Again thank you.

PaulS

Quote
What I want it to do, is to sleep the entire time if the acceleration signal does not exceed a specific value.
How will you know that the acceleration value, along some axis, has exceeded some value, while you are sleeping? Unless you can program the IMU to output a digital signal when that happens?

You'll need to read the datasheet to see if you can do that.

Quote
- attachInterrupt(0,wake,RISING) calls a function "wake" that wakes the system once the input of 0 is rising
- as soon as the RISING state is finished, everything retuns to sleep by continuing loop()
If you can make the device output a suitable signal, the "rising state is finished" as soon as the signal triggers the interrupt handler. You do NOT want to immediately go back to sleep. You want to pay attention of the value(s) from the IMU and only go back to sleep when the output(s) from the IMU indicate that it is stopped.
The art of getting good answers lies in asking good questions.

Go Up