arduino pro mini wake up from sleep when gyro z axis changes

Hi

I have made a code to send gyro x,y and z values every 4 seconds from one arduino to another using nrf24l01.

here at transmitter side i am using arduino pro mini. so now i want to make changes in transmitting data, when there is change in the gyro z axis only then arduino pro mini should come out of sleep and send data.

can some one please help me to do this changes.

here is my transmitter code which i have to send data every 4 seconds.

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <SPI.h>
#include "RF24.h"

 #include <Wire.h>


// Changing transmitter num
#define TRANSMITER_NUM    0 // or 1

const int MPU = 0x68; // MPU6050 I2C address
    float AccX, AccY, AccZ;
    float GyroX, GyroY, GyroZ;
    float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
    float roll, pitch, yaw;
    float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
    float elapsedTime, currentTime, previousTime;

const uint64_t talking_pipes[2] = { 0xF0F0F0F0D1LL, 0xF0F0F0F0C2LL };


struct DataPacket {
  int   voltage;
  int   x;
  int   y;
  int   z;
};



RF24 radio(7,8);



void watchdogSetup(void)
{
  wdt_reset();

  
WDTCSR = bit (WDCE) | bit (WDE) | bit (WDIE) | bit (WDP3)| bit (WDP2) | bit (WDP1);    
 
}




void disableHardware() {
//  radio.sleep();          // Set the radio transceiver in sleep mode
  radio.powerDown();              // NOTE: The radio MUST be powered back up again manually
  power_spi_disable();    // Disable the Serial Peripheral Interface module.
  power_timer0_disable(); // Disable the Timer 0 module..
  power_timer1_disable(); // Disable the Timer 1 module.
  power_timer2_disable(); // Disable the Timer 2 module  
  power_twi_disable();    // Disable the Two Wire Interface module.  
  //power_usart0_disable(); // Disable the USART 0 module.
  ADCSRA &= ~(1 << ADEN); // Ensure AD control register is disable before power disable
  power_adc_disable();    // Disable the Analog to Digital Converter module

 //adxl.setLowPower(true);
}
void enableHardware() {
  power_spi_enable();    // Enable the Serial Peripheral Interface module.
  power_timer0_enable(); // Enable the Timer 0 module..
  power_timer1_enable(); // Enable the Timer 1 module.
  power_timer2_enable(); // Enable the Timer 2 module  
  power_twi_enable();    // Enable the Two Wire Interface module.  
#ifdef SERIAL_PRINT
  power_usart0_enable(); // Enable the USART 0 module.
#endif
  power_adc_enable();    // Enable the Analog to Digital Converter module

  radio.powerUp();       // Power up the radio after sleeping

}


void enterSleep(void)
{ADCSRA = 0; 
  sleep_enable();

  disableHardware();

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
    MCUSR = 0;
  watchdogSetup();

  sleep_cpu();
 
  sleep_disable();

  enableHardware();
}




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


  radio.begin();


  radio.setPALevel(RF24_PA_MAX);

  radio.setDataRate(RF24_250KBPS);
 
  radio.setChannel(0x50);

  radio.openWritingPipe(talking_pipes[TRANSMITER_NUM]);
  
 
  getBandgap();
#ifdef SERIAL_PRINT
  Serial.println("Initialisation complete.");
#endif
}




ISR (WDT_vect) 
{
   wdt_disable();  // disable watchdog
}  // end of WDT_vect



const long InternalReferenceVoltage = 1100;  // Adjust this value to your board's specific internal BG voltage

int getBandgap () 
{
   ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
   ADCSRA |= bit( ADSC );  // start conversion
   while (ADCSRA & bit (ADSC))
     { }  // wait for conversion to complete (toss this measurement)
   ADCSRA |= bit( ADSC );  // start conversion
   while (ADCSRA & bit (ADSC))
     { }  // wait for conversion to complete
   int results = (((InternalReferenceVoltage * 1024) / ADC) + 5) / 10; 
   return results;
} 


int cnt=0;
void loop()
{
  bool sendValue = false;
  DataPacket data;
  
  cnt++;
  if (cnt >=1 ) { // send EVERY time wakeup happens
    cnt = 0;
    sendValue = true;
  }

 

  if (sendValue) {
    cnt = 0;
    data.voltage = getBandgap();
    
     Wire.begin();                      // Initialize comunication
      Wire.beginTransmission(MPU);       // Start communication with MPU6050 // MPU=0x68
      Wire.write(0x6B);                  // Talk to the register 6B
      Wire.write(0x00);                  // Make reset - place a 0 into the 6B register
      Wire.endTransmission(true); 

    Wire.beginTransmission(MPU);
      Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 6, true); 
     
      AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
      AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
      AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
      // Calculating Roll and Pitch from the accelerometer data
      accAngleX = (atan(-1*AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
      accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
     
      Wire.beginTransmission(MPU);
      Wire.write(0x43); // Gyro data first register address 0x43
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 6, true); 
      GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; 
      GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
      GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
     
      GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
      GyroY = GyroY - 2; // GyroErrorY ~(2)
     GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
      
    
      gyroAngleX = gyroAngleX ; // deg/s * s = deg
      gyroAngleY = gyroAngleY;
      yaw = GyroZ;
     
      roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
      pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
           
    data.x = accAngleX;
    data.y = accAngleY;
    data.z = yaw;
     Serial.print(data.x);
      Serial.print("/");
      Serial.print(data.y);
      Serial.print("/");
      Serial.println(data.z);
  
   radio.write( &data, sizeof(data) );
  }
  enterSleep();
}

Check if your gyro has an interrupt output that fits your needs.

DrDiettrich:
Check if your gyro has an interrupt output that fits your needs.

Gyro has interrupt. but it works on all the axis. i want to make it only on z axis

Why Z axis only? For permanent monitoring the Arduino must run permanently or at least without much sleep in between the measurements.

Gyro has interrupt. but it works on all the axis. i want to make it only on z axis

Have the interrupt wake up the Arduino, check the change, and if the change is not in the Z axis, go back to sleep.

In my case now arduino is not consuming more power. Mpu6050 is consuming around 3.8mA how this can be reduced?

You can turn off unneeded MPU6050 functions, but the gyroscope consumes most of the power (about 3.6 mA).

If the gyroscope is supposed to wake the Arduino, you have to power it continuously.

Hi

Is there any option to make mpu6050 consumes very less power? in few posts i saw that it consumes around 50microampers