TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: Ranculche 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
#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;
}
-
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:
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
-
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?
-
Ninguna. Entonces queda el tema de las entradas/salidas que pueden estar consumiendo de mas.
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.
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.
-
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.
-
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:
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