Autor Tema: SLEEP y consumo  (Leído 1519 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Ranculche

  • PIC12
  • **
  • Mensajes: 74
SLEEP y consumo
« en: 10 de Diciembre de 2015, 21:03:16 »
Hola a todos. Esta vez escribo porque tengo un gran problema que pensaba que tenia resuelto y no es asi. El asunto es que tengo una plaqueta con un magnetometro un xbee y un pic16f886. es para usar con bateria y la idea es que dure mucho tiempo, no es para recargar ni reemplazar. La verdad es que pude hacer unas pruebas hace mucho y media unos 25uA. Pero hoy, a un dia de una entrega, me doy con que consume casi 2 mA. A continuacion dejo el programa que uso. Espero puedan darme una mano. Muchas gracias.

Aclaracion. El Hardware interconectado es un pic con su crista de 4MHz, el magnetrometro que mide unos 150uA, el Xbee unos 5uA y un regulador MCP1700T que su consumo por hoja de datos es muy bajo tambien. La alimentacion es con 5 volt ahora, la idea es alimentarlo con 3,7, no se si eso hara variar el consumo

Citar
#include <16F886.h>
#include <stdlib.h>
#fuses XT,NOWDT,NOPUT,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) 

//-------------------------DECLARACIONES DE CONSTANTES----------------------


unsigned long x;
unsigned long y;
unsigned long z;


// i2c slave addresses
#define HMC5883L_WRT_ADDR  0x3C
#define HMC5883L_READ_ADDR 0x3D

// Register addresses
#define HMC5883L_CFG_A_REG 0x00
#define HMC5883L_CFG_B_REG 0x01
#define HMC5883L_MODE_REG  0x02
#define HMC5883L_X_MSB_REG 0x03




#define ACTIVADO   0x41
#define   DESACTIVADO 0x44

//--------------------DECLARACIONES DE FUNCIONES--------------------

void Enviar_Estado(void);
void Procesar_bufferXB(void);
void Leer_EEPROM(void);
void Escribir_EEPROM(void);
void Escribir_EEPROM_XYZ();
void Escribir_EEPROM_MODO();
void Escribir_EEPROM_Pos();
void Leer_EEPROM_XYZ(void);
void Leer_EEPROM_MODO(void);
void Leer_EEPROM_Pos(void);
void Enviar_Error(void);
void Enviar_AT_Reiniciar(void);
void Escribir_UE_EEPROM(void);
void Leer_UE_EEPROM(void);

void hmc5883l_write_reg(int8 reg, int8 data);
int8 hmc5883l_read_reg(int8 reg);
void hmc5883l_read_data(void) ;

//-------------------------DECLARACIONES DE VARIABLES----------------


char    BuferXbB_Tx[30];
char   BufferXB_Rx[30];
char   CBuffer;
char   Estado;
char   Est_Anterior;
unsigned long    SENS=20;
char    Configuracion;
char   Pos;
unsigned long   X_0;
unsigned long   Y_0;
unsigned long   Z_0;
char   Trama_Nueva;
char   Leyendo;
char   Chk_Sum;
char   Etiqueta;
char   contador;
char    aux;
char   recibir;
unsigned long   X1;
unsigned long   Y1;
unsigned long   Z1;
unsigned long   Xn;
unsigned long   Yn;
unsigned long   Zn;
signed long   prueba;
int      dec;
int    i;

char    LSBX,MSBX;

//-----------------------------------PROGRAMA PRINCIPAL---------------------


void main()
{

   DISABLE_INTERRUPTS(GLOBAL);

   ENABLE_INTERRUPTS(INT_RDA);
   CLEAR_INTERRUPT(INT_RDA);

   OUTPUT_LOW(PIN_A1);
   OUTPUT_LOW(PIN_A2);
   OUTPUT_LOW(PIN_A3);
   OUTPUT_LOW(PIN_A4);
   OUTPUT_LOW(PIN_A5);
   OUTPUT_LOW(PIN_A6);
   OUTPUT_LOW(PIN_A7);
   OUTPUT_LOW(PIN_B0);
   OUTPUT_LOW(PIN_B1);
   OUTPUT_LOW(PIN_B2);
   OUTPUT_LOW(PIN_B3);
   OUTPUT_LOW(PIN_B4);
   OUTPUT_LOW(PIN_B5);
   OUTPUT_LOW(PIN_B6);
   OUTPUT_LOW(PIN_B7);
   OUTPUT_LOW(PIN_C1);
   OUTPUT_LOW(PIN_C2);
   OUTPUT_LOW(PIN_C0);
   OUTPUT_LOW(PIN_C5);

   SET_TRIS_A(0X00);
   SET_TRIS_B(0X00);
   

   // Init the HMC5883L.  Set Mode register for
   // continuous measurements.
   hmc5883l_write_reg(HMC5883L_CFG_A_REG,0x70);
   hmc5883l_write_reg(HMC5883L_CFG_B_REG,0xA0);
   hmc5883l_write_reg(HMC5883L_MODE_REG,0x02);

   SETUP_ADC(ADC_OFF);
   
   ENABLE_INTERRUPTS(GLOBAL);


   Leer_EEPROM_MODO();
   output_high(PIN_A0);         //dormir x_bee


   while(1)
   {   
      restart_wdt();
      switch(Configuracion)
      {
         case 0:
   
            output_low(PIN_A0);         //despertar x_bee
            delay_ms(100);
            if(Trama_Nueva==1)
            {
               delay_ms(100);
               Leyendo=0;
               Procesar_bufferXB();
               Trama_Nueva=0;
               
            }
            output_high(PIN_A0);         //dormir x_bee
   
            break;
      
         case 1:
            
            if(contador>=3)
            {
               contador=0;
               output_low(PIN_A0);         //dESPERTAR XBEE   
               delay_ms(100);
               if(Trama_Nueva==1)
               {
                  delay_ms(100);
                  Leyendo=0;
                  Procesar_bufferXB();
                  Trama_Nueva=0;
                  
               }
               output_high(PIN_A0);;
            }
            hmc5883l_write_reg(HMC5883L_MODE_REG, 0x00);
            delay_ms(100);
            hmc5883l_read_data();
            hmc5883l_write_reg(HMC5883L_MODE_REG, 0x01);
            //Enviar_Estado();      //DEBUG: esto es solo para debuguear, BORRAR.
            //COMPLETAR: mejorar el manejo de las variables Long, si se desbordan van a producir errores en la medicion.
            X1=x;
            Y1=y;
            Z1=z;
            Leer_EEPROM_XYZ();
            Leer_UE_EEPROM();
            restart_wdt();
            Xn=X1+0x7FFF+(0xFFFF-X_0);            //Esto lo hacemos para llevar la referencia al centro y que no se desborde
            Yn=Y1+0x7FFF+(0xFFFF-Y_0);            //Esto lo hacemos para llevar la referencia al centro y que no se desborde
            Zn=Z1+0x7FFF+(0xFFFF-Z_0);            //Esto lo hacemos para llevar la referencia al centro y que no se desborde
            if( Xn<(0x7FFF-SENS) || Yn<(0x7FFF-SENS) || Zn<(0x7FFF-SENS) || Xn>(0x7FFF+SENS) || Yn>(0x7FFF+SENS) || Zn>(0x7FFF+SENS))
            {
               Estado=ACTIVADO;
//               output_high(PIN_A0);   
               if(Est_Anterior==DESACTIVADO)
               {
                  Enviar_Estado();
                  Est_Anterior=ACTIVADO;
                  Escribir_UE_EEPROM();
                  
               }
         
            }
            else
            {
               Estado=DESACTIVADO;
//               output_low(PIN_A0);   
               if(Est_Anterior==ACTIVADO)
               {
                  Enviar_Estado();
                  Est_Anterior=DESACTIVADO;
                  Escribir_UE_EEPROM();
               }
         
            }

            break;
         default:
            Enviar_Error();
            break;
      }
      contador++;
      output_high(PIN_A0);         //dormir x_bee
      Setup_oscillator(OSC_31KHZ);      // Probar con esto para consumir menos corriente
      SETUP_WDT(WDT_2304MS | WDT_TIMES_2);
      restart_wdt();
      Sleep();            //El pic pasa a estado de reposo
      SETUP_WDT(WDT_OFF);               
      SETUP_WDT(WDT_OFF);
      Setup_oscillator(OSC_NORMAL);      //Vuelve al estado de reloj inicial

   }    
}


#INT_RDA
void int_rx()
{

   if(kbhit())
   {
      recibir=getc();
      if(recibir==0x7E)
      {
         CBuffer=0;
         Trama_Nueva=1;
         BufferXB_Rx[0]=recibir;
         CBuffer++;   
      }
      else
      {
         BufferXB_Rx[CBuffer]=recibir;
         CBuffer++;
         Leyendo=1;
      }
   CLEAR_INTERRUPT(INT_RDA);
   }
}


void Enviar_Estado(void)
{   
   restart_wdt();
   Chk_Sum=0;
   output_low(PIN_A0);         //despertar x_bee
   delay_ms(100);
   Leer_EEPROM_Pos();
   delay_ms(10);
   BuferXbB_Tx[0]=0x7E;         //Primer caracter de todas la tramas
   BuferXbB_Tx[1]=0x00;         //MSB del tamaño de la trama desde la posicion 3
   BuferXbB_Tx[2]=0x11;            //LSB  "   "      "      "
   BuferXbB_Tx[3]=0x10;            //Tipo de trama Xbee
   BuferXbB_Tx[4]=0x01;
   BuferXbB_Tx[5]=0x00;
   BuferXbB_Tx[6]=0x00;
   BuferXbB_Tx[7]=0x00;
   BuferXbB_Tx[8]=0x00;
   BuferXbB_Tx[9]=0x00;
   BuferXbB_Tx[10]=0x00;
   BuferXbB_Tx[11]=0x00;
   BuferXbB_Tx[12]=0x00;
   BuferXbB_Tx[13]=0xFF;
   BuferXbB_Tx[14]=0xFE;
   BuferXbB_Tx[15]=0x00;
   BuferXbB_Tx[16]=0x00;
   BuferXbB_Tx[17]=0x00;
   BuferXbB_Tx[18]=Pos;
   BuferXbB_Tx[19]=Estado;         //Acrivado 41 Desactivado 44
   for(i=3;i<20;i++)
   {
      Chk_Sum= Chk_Sum + BuferXbB_Tx;
   }
   Chk_Sum= 0xFF - Chk_Sum;
   BuferXbB_Tx[20]=Chk_Sum;
   restart_wdt();
   for(i=0;i<21;i++)
   {
      putchar(BuferXbB_Tx);   
   }
   delay_ms(100);
   output_high(PIN_A0);         //dormir x_bee

}

void Enviar_AT_Reiniciar(void)
{
   restart_wdt();
   Chk_Sum=0;
   output_low(PIN_A0);         //despertar x_bee
   //COMPLETAR: IMPORTAR LA FUNCION PARA MANDAR DATOS.
   BuferXbB_Tx[0]=0x7E;            //Primer caracter de todas la tramas
   BuferXbB_Tx[1]=0x00;            //MSB del tamaño de la trama desde la posicion 3
   BuferXbB_Tx[2]=0x04;            //LSB  "   "      "      "
   BuferXbB_Tx[3]=0x08;            //Tipo de trama Xbee
   BuferXbB_Tx[4]=0x01;
   BuferXbB_Tx[5]=0x46;
   BuferXbB_Tx[6]=0x52;
      
   for(i=3;i<7;i++)
   {
      Chk_Sum= Chk_Sum + BuferXbB_Tx;
   }
   Chk_Sum= 0xFF - Chk_Sum;
   BuferXbB_Tx[7]=Chk_Sum;
   for(i=0;i<8;i++)
   {
      putchar(BuferXbB_Tx);   
   }
   delay_ms(100);
   output_high(PIN_A0);         //dormir x_bee

}

void Procesar_bufferXB(void)
{
   restart_wdt();
   switch (BufferXB_Rx[3])
   {
      case 0x90:                  //Recepcion de datos
         Switch(BufferXB_Rx[15])      //COMPLETAR: Aca hay que sacar la informacion de la trama de datos, Posicion y lo que sea necesario
         {
            case 0x01:            //Esta es una etiqueta interna 0X01: Configuracion
               hmc5883l_write_reg(HMC5883L_MODE_REG, 0x00);
               delay_ms(100);
               hmc5883l_read_data();
               hmc5883l_write_reg(HMC5883L_MODE_REG, 0x02);
               X_0=x;
               Y_0=y;
               Z_0=z;
               Pos=BufferXB_Rx[16];
               Configuracion=1;
               Escribir_EEPROM();
            break;
            case 0x02:            //Esta es una etiqueta interna 0x02: Configura posicion nuevamente
               Pos=BufferXB_Rx[16];
               Escribir_EEPROM_Pos();   
            break;
            case 0x03:            //Esta es una etiqueta interna que llevan todos las transmisiones de datos, 0x01 indica configurarse o reconfigurarse
               hmc5883l_write_reg(HMC5883L_MODE_REG, 0x00);
               delay_ms(100);
               hmc5883l_read_data();
               hmc5883l_write_reg(HMC5883L_MODE_REG, 0x02);
               X_0=x;
               Y_0=y;
               Z_0=z;
               Escribir_EEPROM_XYZ();
            break;
         
            break;
         }
      break;

      case 0x8A:      // Recepcion de comando AT
         switch(BufferXB_Rx[4])
         {
            //COMPLETAR:reiniciar el xbee por cambio de idpan
            case 0x03:   
               Enviar_AT_Reiniciar();         //mandar comando at para reiniciar
         
         }
      break;
   }

}


void Escribir_EEPROM(void)
{
   restart_wdt();
   Escribir_EEPROM_Pos();
   Escribir_EEPROM_XYZ();
   Escribir_EEPROM_MODO();
}

void Escribir_EEPROM_Pos()
{
   restart_wdt();
   write_EEPROM(0x10,Pos);
}
void Escribir_EEPROM_XYZ()
{   
   restart_wdt();
   char LSBX, LSBY, LSBZ, MSBX, MSBY, MSBZ;
   LSBX= X_0 & 0xFF;
   MSBX=(X_0>>8) & 0xFF;
   write_EEPROM(33,LSBX);
   write_EEPROM(32,MSBX);
   LSBY= Y_0 & 0xFF;
   MSBY=(Y_0>>8) & 0xFF;
   write_EEPROM(49,LSBY);
   write_EEPROM(48,MSBY);   
   LSBZ= Z_0 & 0xFF;
   MSBZ=(Z_0>>8) & 0xFF;
   write_EEPROM(65,LSBZ);
   write_EEPROM(64,MSBZ);

}

void Escribir_EEPROM_MODO()
{
   restart_wdt();
   write_EEPROM(0,Configuracion);
}

void Leer_EEPROM(void)
{   
   restart_wdt();
   Leer_EEPROM_XYZ();
   Leer_EEPROM_MODO();
   Leer_EEPROM_Pos();
}

void Leer_EEPROM_XYZ(void)
{
   restart_wdt();
   char LSBX,MSBX,LSBY,MSBY,LSBZ,MSBZ;
   LSBX=read_EEPROM(33);
   MSBX=read_EEPROM(32);
   X_0=(0xFFFF & MSBX)<<8;
   X_0= X_0 | LSBX;
   LSBY=read_EEPROM(49);
   MSBY=read_EEPROM(48);
   Y_0=(0xFFFF & MSBY)<<8;
   Y_0= Y_0 | LSBY;
   LSBZ=read_EEPROM(65);
   MSBZ=read_EEPROM(64);
   Z_0=(0xFFFF & MSBZ)<<8;
   Z_0= Z_0 | LSBZ;
}

void Leer_EEPROM_MODO(void)
{

   Configuracion=read_EEPROM(0);
}

void Leer_EEPROM_Pos()
{

   Pos=read_EEPROM(0x10);
}

void Escribir_UE_EEPROM(void)
{
   write_EEPROM(80,Est_Anterior);
}

void Leer_UE_EEPROM(void)
{
   Est_Anterior=read_EEPROM(80);
}
void Enviar_Error(void)
{return;}


//------------------------------
// Funciones de I2C- Magnetometro
//------------------------------
void hmc5883l_write_reg(int8 reg, int8 data)
{
   restart_wdt();
   i2c_start();
   i2c_write(HMC5883L_WRT_ADDR);
   i2c_write(reg);
   i2c_write(data);
   i2c_stop();
}

//------------------------------
int8 hmc5883l_read_reg(int8 reg)
{
   restart_wdt();
   int8 retval;
   i2c_start();
   i2c_write(HMC5883L_WRT_ADDR);
   i2c_write(reg);
   i2c_start();
   i2c_write(HMC5883L_READ_ADDR);
   retval = i2c_read(0);
   i2c_stop();
   return(retval);
}


//------------------------------
void hmc5883l_read_data(void)
{
   restart_wdt();
   int8 x_lsb;
   int8 x_msb;
   
   int8 y_lsb;
   int8 y_msb;
   
   int8 z_lsb;
   int8 z_msb;
   restart_wdt();
   i2c_start();
   i2c_write(HMC5883L_WRT_ADDR);
   i2c_write(HMC5883L_X_MSB_REG);  // Point to X-msb register
   i2c_start();
   i2c_write(HMC5883L_READ_ADDR);
   restart_wdt();
   x_msb = i2c_read();
   x_lsb = i2c_read();
   restart_wdt();
   y_msb = i2c_read();
   y_lsb = i2c_read();
   restart_wdt();
   z_msb = i2c_read();
   z_lsb = i2c_read(0);   // do a NACK on last read
   restart_wdt();
   i2c_stop();
    
   // Combine high and low bytes into 16-bit values.
   x =make16(x_msb, x_lsb);
//   (signed long) compass.x;
   y = make16(y_msb, y_lsb);
//   (signed long) compass.y;
   z = make16(z_msb, z_lsb);
//   (signed long) compass.z;
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:SLEEP y consumo
« Respuesta #1 en: 10 de Diciembre de 2015, 22:00:23 »
Primero intentaria determinar que es lo que causa el consumo

El Xbee si puede llegar a eso pero creo que en un estado casi totalmente apagado. (Ese consumo parece un poco ideal, pero en recepcion/trasmision debe consumir lindo)
El tipico del PIC con 4Mhz va de .9 a 1.4mA @5V & 25ºC y eso hay que sumarle la corriente de salida de cada uno de los pines mientras esta funcionando.
El oscilador no depende del Sleep y deberias tener como maximo 9uA, si es que tenes desactivado el BOR / ADC / Comparadores y el oscilador del TMR1

Y recalco esto:

Citar
The power-down current in Sleep mode does not depend on the oscillator type. Power-down current is measured with the part in Sleep mode, with all I/O pins in high-impedance state and tied to VDD.

No flotando
Si no pudieras tenerlo a VDD, imagino que lo mejor sera una salida la cual cause el menor consumo posible, aunque vas a tener consumo de la etapa del driver + circuito externo.

Yo apuntaria a:

- El Xbee
- Entradas

Si tenes la posibilidad de quitar el modulo Xbee y que funcione todo, entonces hacelo y medilo
« Última modificación: 10 de Diciembre de 2015, 22:19:04 por KILLERJC »

Desconectado Ranculche

  • PIC12
  • **
  • Mensajes: 74
Re:SLEEP y consumo
« Respuesta #2 en: 10 de Diciembre de 2015, 23:15:25 »
HOLA GRACIAS POR RESPONDER!! Te cuento que he sacado el xbee y no varia el consumo, el magnetometro tiene un consumo de 150 uA y solo me queda el pic y el regulador, que los tengo soldados (ambos son SMD). Necesito muy poco tiempo prendido el xbee, solo cuando mido algun cambio, ahi transmito, dormido consume muy muy poco. Al pic tambien lo duermo, y habia probado en otras opurtinidades (No encuentro ese soft, era una placa casi igual) y consumia muy poco tambien, he probado apagando los dispositivos como adc, etc etc, y es igual. talves deberia cargarle un programa basico y ver. No se tampoco que hacer con la I2C y la UART a la hora de dormir. En aquella oportunidad era muy basico el programa y lo alimentaba con 3.6 al circuito. Alguna otra idea?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:SLEEP y consumo
« Respuesta #3 en: 10 de Diciembre de 2015, 23:28:30 »
Ninguna. Entonces queda el tema de las entradas/salidas que pueden estar consumiendo de mas.

Citar
For lowest current consumption in this mode, all I/O pins should be either at VDD or VSS, with no external circuitry drawing current from the I/O pin and the comparators and CVREF should be disabled. I/O pins that are high-impedance inputs should be pulled high or low externally to avoid switching currents caused by floating inputs. The T0CKI input should also be at VDD or  VSS for lowest current consumption. The contribution from on-chip pull-ups on PORTA should be considered. The MCLR pin must be at a logic high level.

Citar
No se tampoco que hacer con la I2C y la UART a la hora de dormir.

Segun el datasheet el I2C puede sacarlo de la condicion de sleep si es que se recibe algo, por lo cual parece que sigue "conectado", la UART habilita la recepcion solo si es esclavo, lo cual tambien sigue conectado


PD:

      restart_wdt();
      Sleep();   

Supuestamente el comando SLEEP resetea el WDT

Y si no tenes necesidad de demasiada velocidad, usas directamente el oscildor interno interno, ya que tenes de 32, 125,250 a 8Mhz para elegir, creo que con 500Khz tenes los 9600 baudios.
Pero supongo que es por las entradas. podrias probar al salir del sleep, si correctamente entro al mismo mirando los bits de estado. para saber realmente que entra al modo.
« Última modificación: 11 de Diciembre de 2015, 04:37:59 por KILLERJC »

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:SLEEP y consumo
« Respuesta #4 en: 11 de Diciembre de 2015, 14:03:55 »
Que tal Ranculche,

Definitivamente tienes que revisar que tus puertos de entrada en el PIC no esten flotados, por experiencia yo recomiendo conectarlos a VSS y no a VDD ya que así garantizas que no hay flujo de corriente hacia el micro (asegurate de que las resistencias de pull-up esten apagadas, de lo contrario por ahí tambien se fuga la corriente).
Por lo que veo en tu codigo, solamente el WDT es quien despierta al micro ya que no habilitaste el bit de WUE del puerto serial, por lo que eso no es problema.
Definitivamente la corriente que tienes de fuga es por los puertos de entrada que estan flotados.

Algo que veo extranio es el magnetometro, no pude encontrar en donde lo estes habilitando o deshabilitando. Aunque bien mencionas que este consume 150 uA, no menciones el numero de parte para revisar su hoja de datos y ver si hay algun detalle que se te pudiera haber pasado.

Saludos,

Elreypic.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:SLEEP y consumo
« Respuesta #5 en: 11 de Diciembre de 2015, 15:07:59 »
Algo que veo extranio es el magnetometro, no pude encontrar en donde lo estes habilitando o deshabilitando. Aunque bien mencionas que este consume 150 uA, no menciones el numero de parte para revisar su hoja de datos y ver si hay algun detalle que se te pudiera haber pasado.

Yo lo saque desde el codigo:

#define HMC5883L_CFG_A_REG 0x00

https://www.seeedstudio.com/wiki/images/4/42/HMC5883.pdf

Donde supongo que lo usa con single supply ( para tener solo 3.3v por eso el regulador imagino), y alli tenes los valores de las corrientes, aun incluso midiendo el maximo es de 0.7mA.

Lo cual puede parecer que no entra en modo sleep, consume lo normal el PIC (0.9 a 1.4mA) y como esta leyendo continuamente vea los 2mA.
Sino como bien dijiste es por las entradas.

El mayor tema es este:

Citar
Pero hoy, a un dia de una entrega

No creo que posea tiempo para cambiar el PCB o arreglarlo, por que no parece error de soft


 

anything