[Solucionado] Alimentar mpu6050 con salida digital de Arduino Pro Mini

Hola a todos.
Soy nuevo en el foro y también realmente en el mundo Arduino.

Me presento. Mi nombre es Juan Carlos y estoy trabajando en un proyecto donde necesito tomar datos de posición y temperatura de un falso huevo incubado por un ave.

La idea es poner un huevo hueco, de plástico, con un proyecto dentro que mida los datos de posición y temperatura y los grabe en una tarjeta microSD y así extrapolar estos datos para proogramar una incubadora para que ésta trate de emular la incubación natural girando y cambiando la temperatura de los huevos naturales puestos en la incubadora para aumentar la tasa de éxito de eclosión de los mismos.

Estoy usando un Arduino Pro mini de 5 volts, un mpu6050 (giroscopio-acelerómetro), un módulo lector/grabador en tarjeta microSD y 3 termistores NTC.

El problema está en que necesito meter todo el sistema (incluyendo batería) en un huevo de plástico de unos 60 x 40 mm.

He medido consumos y el mpu tirnr unos 5 mA, el arduino unos 17 mA, el módulo de tarjeta microSD unos 5 mA y cada termistor unos 0,3 mA. Total unos 28mA.

Me cabe dentro una batería Li-Po de 300 mA, con lo que tendría a lo sumo unas 10 horas. Pero necesito que me mida al menos 5 ó 6 días, si es más mejor.

He usado la librería lowpower con la función LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); y eso me reduce el consumo del arduino mientras está en sleep pero no lo suficiente. Por otra parte esta función no desactiva la alimentación de los sensores así que éstos siguen consumiendo.

He intentado alimentarlos con una salida digital del Arduino y así encenderlos sólo cuando el arduino despierta cada 8 seg.
El problema es que al iniciar el MPU6050 en el setup, la salida digital nunca despierta, así que los sensores nunca se alimentan.

Debo estar haciendo algo mal a este respecto.
¿Podría alguien echar un vistazo al código e indicarme algún error que esté cometiendo?

Muchas gracias por anticipado

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
#include <TimeLib.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
#include "LowPower.h"  //Libreria de ahorro de bateria 
#include <SD.h>
#include <math.h>   //Libreria termistor
#include "LowPower.h"  //Libreria de ahorro de bateria 

const int mpuAddress = 0x68;  // Puede ser 0x68 o 0x69
MPU6050 mpu(mpuAddress);
int ax, ay, az;
int gx, gy, gz;  //Acaba 6050

const int pin = 10; // Usaré este PIN como salida de Vcc para alimentar los sensores

const int Rc = 10000; //valor de la resistencia del termistor -  aqui empiea el termistor
const int Vcc = 5;
const int SensorPIN = A3;
 
float A = 1.11492089e-3;
float B = 2.372075385e-4;
float C = 6.954079529e-8;
 
float K = 2.5; //factor de disipacion en mW/C  // aqui acaba el termistor

File myFile; //Para el archivo que se creara en la microSD

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

 while (!Serial) ; // Needed for Leonardo only
 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 setTime(10 , 40 , 00 , 22, 02, 2020); // Pone en hora el reloj RTC (p ej. Las 10:40:00 del dia 22 de Feb de 2020)
  if (timeStatus() != timeSet) 
 
 Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time"); 
  
 Wire.begin(); //empieza MPU6050
   mpu.initialize();
   Serial.println(mpu.testConnection() ? F("IMU iniciado correctamente") : F("Error al iniciar IMU")); //acaba MPU6050
  
  Serial.print("Iniciando MicroSD ...");
  if (!SD.begin(4)) {
    Serial.println("No se pudo inicializar");
    return;
  }
  Serial.println("MicroSD Iniciada correctamente");

  if(!SD.exists("datalog.csv"))
  {
      myFile = SD.open("datalog.csv", FILE_WRITE);
      if (myFile) {
        Serial.println("Archivo nuevo, Escribiendo encabezado(fila 1)");
        myFile.println("Tiempo(Tiempo;Sensor1;Sensor2;Sensor3;sensor4;sensor5");
        myFile.close();
      } else {

        Serial.println("Error creando el archivo datalog.csv");
        pinMode(10, OUTPUT); //define el PIN 10 como salida
      }
  }
}

void loop( )
{
delay (500);//un pequeño retardo para que el sistema despierte correctamente y los sensores puedan dar datos

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //Ponemos el Arduino en modo sleep durante 8 seg

digitalWrite(10, HIGH);   // Pone la salida 8 en High para alimentar los sensores
  delay(1000);                       // espera un segundo en high
  digitalWrite(10, LOW);    // Apaga la salida 8 y los sensores
  
   
   // Leer las aceleraciones  del MPU6050
   mpu.getAcceleration(&ax, &ay, &az);
 
   //Calcular los angulos de inclinacion
   float accel_ang_x = atan(ax / sqrt(pow(ay, 2) + pow(az, 2)))*(180.0 / 3.14);
   float accel_ang_y = atan(ay / sqrt(pow(ax, 2) + pow(az, 2)))*(180.0 / 3.14);
 
   // Mostrar resultados
  
  
   float raw = analogRead(SensorPIN);  //aqui empieza termistor
  float V =  raw / 1024 * Vcc;
 
  float R = (Rc * V ) / (Vcc - V);
  
 
  float logR  = log(R);
  float R_th = 1.0 / (A + B * logR + C * logR * logR * logR );
 
  float kelvin = R_th - V*V/(K * R)*1000;
  float celsius = kelvin - 273.15-1;  //aqui acaba el termistor
  {
    
   Serial.print(day());
  Serial.print("-");
  Serial.print(month());
  Serial.print("-");
  Serial.print(year());
   Serial.print("  ");
  Serial.print(hour());
    Serial.print(":");
 Serial.print(minute());
 Serial.print(".");
 Serial.print(second()); 
     
     Serial.print(";   T = ");  //aqui empieza termistor
  Serial.print(celsius);
  Serial.print("C");  //aqui acaba termistor
  
     Serial.print(F("\;    Inclinacion en X:"));
   Serial.print(accel_ang_x);
   Serial.print(F(";             \Inclinacion en Y: "));
   Serial.println(accel_ang_y);

     myFile = SD.open("datalog.csv", FILE_WRITE);//abrimos  el archivo
  
  if (myFile) { 
        Serial.print("");
        
    myFile.print(day());
  myFile.print("-");
  myFile.print(month());
  myFile.print("-");
  myFile.print(year());
   myFile.print("  ");
  myFile.print(hour());
    myFile.print(":");
 myFile.print(minute());
 myFile.print(".");
 myFile.print(second()); 
  
          myFile.print(";   T = ");  //aqui empieza termistor
  myFile.print(celsius);
  myFile.print("C");  //aqui acaba termistor
  myFile.print( ";     T = " );


       myFile.print(F("\;    Inclinacion en X:"));
   myFile.print(accel_ang_x);
   myFile.print(F(";             \Inclinacion en Y: "));
   myFile.println(accel_ang_y);
        
        myFile.close(); //cerramos el archivo
 
  
  } else {
    Serial.println("Error al abrir el archivo");
   
  }

  }
  
     }

Una alternativa que no se si sería ecológicamente tolerable sería usar un cargador inalámbrico para tu batería.
Mas allá de lo reducido del tamaño, podrías recargar la batería via RF cada X horas asegurándote la carga y la duración del sistema.Por supuesto que no tengo idea del tamaño o volumen que ocuparía un cargador así.

Muchas gracias por la pronta respuesta.
La verdad es que he sopesado esa posibilidad pero pensé que debía haber contacto entre la batería y el cargador. Investigando un poco más veo que no es necesario ese contacto, así que voy a seguir este hilo de investigación.
Muchas gracias :slight_smile:

De todos modos, si alguien tiene ideas sobre cómo apagar los sensores el tiempo que no es necesario que tomen datos, por supuesto serán muy bienvenidas :slight_smile:

Lo primero es tu sistema de recarga.
Apagar los sensores se hace con un transistor PMOS o sea un MOSFET canal P de bajo Rds.

Amplío mi respuesta: No solo puedes usar un PMOS o MOSFET Canal P. Eso es para controlar la energia desde el positivo al sensor.
Del mismo modo puedes usar un MOSFET Canal N o NMOS y controlar el negativo o retorno a gnd desde el sensor.

Acá tienes un ejemplo con un ESP8266 que controla un sensor usando un PMOS

Muchas gracias nuevamente.
Para apagar los sensores y encenderlos cada cierto tiempo, de dónde puedo sacar la señal que ponga en corte o en saturación al transistor? Con el código y la configuración que estoy usando, al dormir el Arduino con la función lowpower.powerDown, la salida digital elegida para alimentar los sensores cada 8 seg no se pone en high nunca una vez que el mpu6050 se inicia con la función mpu.initialize(); en el setup

Por otra parte, y para continuar investigando también por esa parte, sabes de algún cargador inalámbrico (sin contacto) que pueda cargar la batería Li-Po cada cierto tiempo?

Muchas gracias por tu atención

Con el código y la configuración que estoy usando, al dormir el Arduino con la función lowpower.powerDown, la salida digital elegida para alimentar los sensores cada 8 seg no se pone en high nunca una vez que el mpu6050 se inicia con la función mpu.initialize();

las cosas se hacen antes o después.
Antes de ponerlo a dormir desactivas la energia en el MPU via el PMOS.
Al despertar activas el PMOS de la misma manera.
No es complicado. Un LOW va a activar el PMOS y un HIGH lo va a desactivar.
Entonces un LOW energiza el MPU y un HIGH en dicho transisto lo apaga.

Eso lo repites para cuanto sensor uses y asi tendrás mejor aprovechamiento de tu batería.

Muchas gracias por tu respuesta surbyte.
Voy a comprar un PMOS y a probarlo.
Para alimentar el sistema he visto un Módulo de Alimentación 5V Paso Arriba para Lilypad AAA. Básicamente eleva la tensión de una batería AAA desde 1,5 Volt a 5 Volt. Si le pongo una AAA de 1100mA y este módulo me lo pasa a 5 Volt, ¿crees que puede servir?.

Gracias por tu atención y paciencia

Este es un tema de hardware antes que de Software de modo que lo muevo a dicha sección.

No compres cualquier PMOS o MOSFET Canal P. Debes observar con cuidado cual usar porque debe tener un bajo Rds o sea, una baja resistencia cuando este conduciendo para alimentar tu sensor y de ese modo tener una caída de tensión despreciable, tal que haga que tu sensor no funcione adecuadamente.
Por eso te hice la observación.

Me puse a buscar tu caso y es curioso, pero el MPU6050 consume hasta 1.74 mA (según este hilo ver abajo consumo del MPU6050) cuando esta entregando datos y cae a 0.14mA cuando deja de hacerlo.
Prueba comandarlo directamente con tu pin sin ningún MOSFET. Si usas un Arduino el pin puede drenar hasta 40mA y si usaras un ESP habría que ver pero creo que andaba en los 12mA.
Ambos entonces pueden comandar al MPU6050.

Según el manual del MPU6050, este consume

Gyroscope operating current: 3.6mA
Standby current: 5μA

y esto lo pongo porque nunca confío en lo que leo en otros post.

Entonces confirmado, prueba con el PIN comandando directamente el MPU6050 y ahora si,comprueba que la tensión de salida cuando lo activas sea la esperada.

Gracias de nuevo surbyte.
Disculpa la tardanza en la respuesta. Estoy unos días fuera y apenas tengo conexión. Midiendo consumo el mpu6050 me consumía 5 mA.
Voy a hacer lo que me dices en cuanto llegue de nuevo a casa y te comentaré el resultado.
Gracias por tu atención

Hola nuevamente surbyte,
He retomado el proyecto de nuevo.
Estoy alimentando el mpu con la salida digital y, aunque la tensión que presenta es correcta (5 volts), el mensaje que presenta por el puerto serie es “error al iniciar MPU”. Las lecturas que presenta el mpu también son con error (x=nan Y=nan)
La verdad es que no sé dónde puede estar el problema. ¿Me puedes echar un cable?

Gracias por tu atención

Seguramente has habilitado no precisamente en el momento adecuado.

Prueba con esto, solo muestro la parte relevante

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

#define PIN_MPU    2
const int mpuAddress = 0x68;  // Puede ser 0x68 o 0x69
MPU6050 mpu(mpuAddress);


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

 while (!Serial) ; // Needed for Leonardo only
 setSyncProvider(RTC.get);   // the function to get the time from the RTC
 pinMode(PIN_MPU, OUTPUT);
 digitalWrite(PIN_MPU, HIGH);
 delay(10);
 
 Wire.begin(); //empieza MPU6050
 mpu.initialize();
 Serial.println(mpu.testConnection() ? F("IMU iniciado correctamente") : F("Error al iniciar IMU")); //acaba MPU6050
  
}

Muchas gracias por tu rápida respuesta.
He cambiado la parte de código tal y como me has indicado pero de este modo no ha llegado a alimentar al mpu. Sin embargo, me has proporcionado la clave con el delay que has usado de 10mseg justo después de poner el pin de salida en high.
He aplicado este delay al codigo que estaba usando antes y... perfecto!! el mpu se ha inicado y está funcionando.
EL código (lo que nos interesa) quedaría así:

const int pin = 8; // Usaré este PIN como salida de Vcc para alimentar los sensores

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

   pinMode(8, OUTPUT); //define el PIN 8 como salida
   digitalWrite(8, HIGH);
   delay (10);

 while (!Serial) ; // Needed for Leonardo only
 setSyncProvider(RTC.get);   // the function to get the time from the RTC

 setTime(10 , 40 , 00 , 22, 02, 2020); // Pone en hora el reloj RTC (p ej. Las 10:40:00 del dia 22 de Feb de 2020)
  if (timeStatus() != timeSet) 
 
 Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time"); 
  
 Wire.begin(); //empieza MPU6050
   mpu.initialize();
   Serial.println(mpu.testConnection() ? F("IMU iniciado correctamente") : F("Error al iniciar IMU")); //acaba MPU6050
   
  Serial.print("Iniciando MicroSD ...");
  if (!SD.begin(4)) {
    Serial.println("MicroSD no se pudo iniciar");
    return;
  }
  Serial.println("MicroSD Iniciada correctamente");

  if(!SD.exists("datalog.csv"))
  {
      myFile = SD.open("datalog.csv", FILE_WRITE);
      if (myFile) {
        Serial.println("Archivo nuevo, Escribiendo encabezado(fila 1)");
        myFile.println("Tiempo(Tiempo;Sensor1;Sensor2;Sensor3;sensor4;sensor5");
        myFile.close();
      } else {

        Serial.println("Error creando el archivo datalog.csv");      
      }
  }
}
void loop( )
{
delay(500);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

Ahora me surgen dos problemas:
El primero es que el módulo de la tarjeta microSD no se inicia cuando es alimentado por la salida digital (el consumo de este módulo medido es de 4,36mA).
El segundo es que con la función LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); la salida digital no se apaga sino que permanece siempre encendida.
De todas formas he conseguido hacer funcionar el mpu con una salida digital, lo que es un gran avance.
Si te parece cierro este hilo como solucionado y abro dos más, uno para cada problema que me ha surgido.
Gracias de nuevo por tu atención y tu paciencia.