Как использовать MPU 6050 в режиме сверхнизкой мощности
В настоящее время я пытаюсь настроить монитор удельного веса брожения, используя датчик наклона. Процесс может занять несколько недель и должен храниться в стерильном контейнере, поэтому он должен питаться от батареи. Я использую слегка модифицированный ESP8266-01, который входит в спящий режим, затем раз в час просыпается, чтобы провести измерение, передать данные и вернуться в спящий режим. Я использую MPU6050 для датчика наклона. Во-первых, я не могу перевести mpu в спящий режим, когда esp выключен, кажется, что он всегда занимает около 4 мА, а во-вторых, мне нужна только одна ось, возможно ли отключить все остальное, чтобы дополнительно снизить энергопотребление? Я не могу найти что-то в руководстве, чтобы отключить оси, только для их калибровки. мой код ниже
экспериментирование с приведенными ниже регистрами, кажется, не имеет никакого значения, добавление их, удаление их все равно занимает около 4 мА. Пробовал установить значение 1, чтобы перевести MPU в спящий режим в конце цикла, но без разницы. Wire.write(0x6B); Wire.write(0);
Я очень новичок в этом, и я изо всех сил пытаюсь интерпретировать руководство, когда оно ссылается на бит 6 в addr 6b, как мне установить бит 6?
Если бы я мог ограничить MPU только до 1 оси, без ускорения и до глубокого сна между измерениями, я бы смог получить энергопотребление около 0,5 мА, что дает мне хорошее время автономной работы при использовании одного 18650. Любой совет был бы очень признателен!
#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();
}
0 ответов
Я новичок в этом, и я изо всех сил пытаюсь интерпретировать руководство, когда оно ссылается на бит 6 в адресе 6b, как мне установить бит 6?
Настроить немного просто. Используйте следующие функции, чтобы избежать мозгового штурма.
// 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();
}
Пример использования: writeRegisterBit(MPU6050_REG_INT_PIN_CFG, 5, 1); //Register 37;Interrupt Latch Enable
Для вашего приложения:
void acclSetSleepEnabled(bool state)
{
writeRegisterBit(MPU6050_REG_PWR_MGMT_1, 6, state);
}
Если бы я мог переустановить MPU только на 1 ось, без ускорения и в глубокий сон между измерениями, я смог бы получить энергопотребление около 0,5 мА, что дает мне хорошее время автономной работы с использованием одного 18650
Чтобы войти в режим акселерометра с низким энергопотреблением, используйте следующую функцию:
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);
}
Этот lowPowerAccel
функция также переводит гироскоп в режим ожидания. Для функции требуется параметр частоты пробуждения. Это определяется следующим образом:
/*
* 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
Надеюсь, я смогу ответить на некоторые ваши вопросы. Удачи!:)
Используете ли вы коммутационную плату для MPU6050? например, GY-521. Часто они используют линейные регуляторы и светодиоды, которые потребляют дополнительную мощность. Возможно, потребуется удалить их и запустить IMU от прямого источника питания.
Каждый регистр в MPU6050 имеет ширину 8 бит. При установке отдельного бита на желаемое значение вы можете либо использовать побитовую манипуляцию (здесь это не практично, поскольку мы не взаимодействуем напрямую с регистрами), либо напрямую установить все биты в регистре в новое состояние регистра, например, 0b00100000 ~ 0x20. Вместо того, чтобы писать от 1 до 0x6B при попытке перевести MPU6050 в спящий режим, вы должны писать 0x20.
https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
Ссылки на стр. 40-42. Если вы хотите сделать что-то еще, вы можете отключить датчик температуры, акселерометры и резервные оси гироскопа для экономии энергии, когда устройство активно.