1

I'm currently trying to set up a fermentation specific gravity monitor, using a tilt sensor. The process can take several weeks, and must be contained in a sterile container, so must be battery powerered. I'm using a slightly modified ESP8266-01, which enters sleep mode then wakes once an hour to take a measurement, transmit the data, and return to sleep mode. I'm using an MPU6050 for the tilt sensor. Firstly, I can't seem to put the mpu into sleep mode when the esp is off, it always seems to take around 4mA, and secondly, I only need one axis, is it possible to disable everything else to limit power consumption further? I can't seem to find anything in the manual to disable axis, only to calibrate them. my code is below

experimenting with the registers below seem to make no difference, adding them, taking them out altogether, still takes around 4mA. Tried setting to 1 to put the mpu to sleep at the end of the cycle but makes no difference. Wire.write(0x6B); Wire.write(0);

I'm very new to this and im struggling to interpret the manual when it refers to bit6 in addr 6b, how do i set bit 6?

If i could restict the mpu to only 1 axis, no acceleration, and to deep sleep inbetween measurements I should be able to get the power consumption around 0.5mA which gives me agood battery life using a single 18650. Any advice would be greatly appreciated!

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "MPU6050.h"
#include "I2Cdev.h"
#include "Wire.h"

// Update these with values suitable for your network.

const char* ssid = "****";
const char* password = "******";
IPAddress server(192, 168, 1, 90);

WiFiClient espClient5;
PubSubClient client(espClient5);
long lastMsg = 0;
char msg[50];
const uint8_t scl = 5; //D1
const uint8_t sda = 4; //D2
int val;
int prevVal = 0;
String pubString;
char gravity[50];
MPU6050 mpu;
const int sleepTimeS = 10; //only 10 seconds for testing purposes, set to 
1hr when operational
int counter=0;


int16_t ax, ay, az;
int16_t gx, gy, gz;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
    Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

}

void callback(char* topic, byte* payload, unsigned int length) { //not 
required in this application
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "test";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("AliveRegister", "FermentMon");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

#define ONE_WIRE_BUS 2  //  D4 on physical board

 OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float prevTemp = 0;

void setup() {
  counter = 0;
  Serial.begin(9600);
  Wire.begin(0,2);
  Wire.write(0x6B); //PWR_MGMT_1 register
  Wire.write(0); // set to zero wakes teh 6050
  Wire.endTransmission(true);
 delay(100);
  setup_wifi();
  client.setServer(server, 1883);
  client.setCallback(callback);
 if (!client.connected()) {
    reconnect();
  }
  Serial.println("Initialize MPU");
  mpu.initialize();
  Serial.println(mpu.testConnection() ? "Connected" : "Connection failed");
 float temp;
  DS18B20.requestTemperatures();
  temp = DS18B20.getTempCByIndex(0); // first temperature sensor
  char buff[100];
  dtostrf(temp, 0, 2, buff);
  temp = temp + 0.5;
  int tRound = int(temp);
   client.publish("Fermenter/temperature", buff);
    Serial.print("Fermenter Temperature: ");
    Serial.println(temp);
    prevTemp = tRound;

  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  val = map(ax, -17000, 17000, 0, 180);
    pubString = String(val);
    pubString.toCharArray(gravity, pubString.length() + 1);
    client.publish("Fermenter/angle", gravity);
    Serial.print("Gravity angle: ");
    Serial.println(val);
    delay(500);
//    counter = counter+1;
    Serial.println("sleep mode");
    Wire.write(0x6B); //PWR_MGMT_1 register
    Wire.write(1); // set to zero wakes teh 6050
    // sleep
    ESP.deepSleep(sleepTimeS * 1000000);
    delay(2000);

  }


void loop() {

  client.loop();

      } 
phil
  • 13
  • 1
  • 8

2 Answers2

1

I'm very new to this and im struggling to interpret the manual when it refers to bit6 in addr 6b, how do i set bit 6?

Setting a bit is simple. Use the follow functions to avoid any brain storming.

// Write register bit
void writeRegisterBit(uint8_t reg, uint8_t pos, bool state)
{
  uint8_t value;
  value = readRegister8(reg);

  if (state)
  {
    value |= (1 << pos);
  } 
 else
  {
    value &= ~(1 << pos);
  }

  writeRegister8(reg, value);
}

// Write 8-bit to register
void writeRegister8(uint8_t reg, uint8_t value)
{
  Wire.beginTransmission(MPU_addr);

#if ARDUINO >= 100
  Wire.write(reg);
  Wire.write(value);
#else
  Wire.send(reg);
  Wire.send(value);
#endif
  Wire.endTransmission();
}

Example Usage: writeRegisterBit(MPU6050_REG_INT_PIN_CFG, 5, 1); //Register 37;Interrupt Latch Enable

For your application:

void acclSetSleepEnabled(bool state)
{
  writeRegisterBit(MPU6050_REG_PWR_MGMT_1, 6, state);
}

If i could restict the mpu to only 1 axis, no acceleration, and to deep sleep inbetween measurements I should be able to get the power consumption around 0.5mA which gives me agood battery life using a single 18650

To enter low power accelerometer mode use the following function:

void lowPowerAccel(uint8_t frequency) {
  uint8_t value;
  value = readRegister8(MPU6050_REG_PWR_MGMT_2);
  value &= 0b00111000;
  value |= (frequency << 6) | 0b111;
  writeRegister8(MPU6050_REG_PWR_MGMT_2, value);

  value = readRegister8(MPU6050_REG_PWR_MGMT_1);
  value &= 0b10010111;
  value |= 0b00111000;
  writeRegister8(MPU6050_REG_PWR_MGMT_1, value);
}

This lowPowerAccel function also puts the gyro to standy mode. The function needs a wake up frequency parameter. This is defined as follows:

/*
  * LP_WAKE_CTRL | Wake-up Frequency
  * -------------+------------------
  * 0            | 1.25 Hz
  * 1            | 2.5 Hz
  * 2            | 5 Hz
  * 3            | 10 H

*/

#define  LP_WAKE_CTRL_1_25        0x00
#define  LP_WAKE_CTRL_2_5         0x01
#define  LP_WAKE_CTRL_5           0x02
#define  LP_WAKE_CTRL_10          0x03

I hope, I could answer some of your questions. Good luck! :)

Tamojit
  • 31
  • 4
0

Are you using a breakout board for the MPU6050? e.g. GY-521. Often they use linear regulators and leds which will consume additional power. It may be necessary to remove these and run the IMU from a direct power source.

Each register in the MPU6050 is 8 bits wide. When setting an individual bit to a desired value you can either use bitwise manipulation (not practical here as we aren't directly interacting with the registers) or directly set all of the bits in the register to the register's new state e.g. 0b00100000 ~ 0x20. Instead of writing a 1 to 0x6B when attempting to put the MPU6050 to sleep you should be writing 0x20.

https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf

Referencing page 40-42, if you want to take things a step further you can disable the temperature sensor, accelerometers, and redundant gyroscope axes to save power while the device is active.

Junkers
  • 443
  • 1
  • 4
  • 9