Other Parts Discussed in Thread: ENERGYTRACE
Hi,
I interfaced proximity sensor vcnl4010. But my requirement is to reduce the current consumption. I'm supplying 3.3v externally from TPS715345 LDO where quiescent current is around 4.8uA. But my problem is i'm not achieving that current instead i'm getting 135uA. Before going to sleep i'm stopping supply to sensor also. Here is my code. Can anyone look into that and give me an idea to achieve low current consumption in the range of 5uA ?
Thankyou,
Manideep
#include "driverlib.h"
#include <msp430.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#define INTERVAL_TIME 58600
#define CR 13
#define LF 10
#define UART_TIMEOUT 9876
#define SLAVE_ADDRESS 0x13
#define CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ 1000
#define CS_SMCLK_FLLREF_RATIO 30
uint8_t TXData=0;
uint8_t RXData=0;
uint8_t reg;
uint32_t result;
uint32_t result1;
uint16_t ID;
uint16_t distance;
unsigned int i;
unsigned int timerflag=0;
unsigned int delayflag=0;
unsigned int Interrupt=0;
char debug_string [123];
void RTC_Int(void);
void uart_init(void);
bool uart_send_debug_string(char []);
bool uart_send_byte(char);
void I2C_init(void);
void clk_init(void);
void LED_Blink(void);
void Transmit(uint8_t);
void Receive(void);
void command_enable(uint8_t,uint8_t);
void Timer_Delay_Init();
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
PM5CTL0 &= ~LOCKLPM5;
clk_init(); // Clock Source Initialization
uart_init(); // UART Initialization
RTC_Int(); // RTC Initialization to wake mcu every 1 minute
TA0CCR0 = 12500; // timer counter to blink led for 100ms
__bis_SR_register(GIE);
while(1)
{
GPIO_setAsOutputPin(GPIO_PORT_P2,GPIO_PIN1);
GPIO_setOutputHighOnPin(GPIO_PORT_P2,GPIO_PIN1);
I2C_init(); // I2C Initialization
LED_Blink();
command_enable(0x80 , 0xFF); // Enabling the Range Bit for Measurement
command_enable(0x82 , 0x00); // Measuring 1.95 Measurements per Second
command_enable(0x83 , 0x10); // LED Current Set to 100mA
Timer_Delay_Init();
while(delayflag==0);
delayflag=0;
Timer_A_stop(TIMER_A1_BASE);
Timer_A_clear(TIMER_A1_BASE);
for(i=10;i>0;i--)
{
Transmit(0x87); // Transmitting MSB Range bit
Receive(); // Receiving MSB Range data
result = RXData;
result = (result<<8);
RXData = 0; // Clearing Received data
Transmit(0x88); // Transmitting LSB Range bit
Receive(); // Receiving LSB Range data
result1 = RXData;
result |= result1; // Adding LSB bit to MSB
RXData = 0; // clearing Received data
distance = exp(log(136000 / result) / 1.765);
sprintf(debug_string,"Distance(cm): %d", distance);
uart_send_debug_string(debug_string); // Displaying Range data
}
GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN1);
__bis_SR_register(LPM4_bits); // Enter LPM3 interrupt
}
}
void Timer_Delay_Init()
{
//Start timer in continuous mode sourced by ACLK
Timer_A_clearTimerInterrupt(TIMER_A1_BASE);
Timer_A_initContinuousModeParam param = {0};
param.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
param.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_16;
param.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
param.timerClear = TIMER_A_DO_CLEAR;
param.startTimer = true;
Timer_A_initContinuousMode(TIMER_A1_BASE, ¶m);
}
void RTC_Int()
{
//Initialize RTC
RTC_init(RTC_BASE,INTERVAL_TIME,RTC_CLOCKPREDIVIDER_1024);
RTC_clearInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT_FLAG);
//Enable interrupt for RTC overflow
RTC_enableInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT);
//Start RTC Clock with clock source SMCLK
RTC_start(RTC_BASE, RTC_CLOCKSOURCE_SMCLK);
}
void I2C_init()
{
// Configure Pins for I2C
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2 + GPIO_PIN3,GPIO_PRIMARY_MODULE_FUNCTION);
// Configuring the Master
EUSCI_B_I2C_initMasterParam param = {0};
param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk = CS_getSMCLK();
param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, ¶m);
}
void Transmit(uint8_t reg)
{
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);
//Set Master in Transmit mode
EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_MODE);
//Enable I2C Module to start operations
EUSCI_B_I2C_enable(EUSCI_B0_BASE);
EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_INTERRUPT0) ;
//Enable master transmit interrupt
EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
TXData = reg;
EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, TXData);
}
void Receive(void)
{
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);
//Set Master in receive mode
EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_RECEIVE_MODE);
// I2C start condition
RXData = EUSCI_B_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);
}
void command_enable(uint8_t command,uint8_t data)
{
//Specify slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);
//Set Master in Transmit mode
EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_MODE);
//Enable I2C Module to start operations
EUSCI_B_I2C_enable(EUSCI_B0_BASE);
EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, command);
EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE,command);
EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE,data);
EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
}
void LED_Blink(void)
{
if(Interrupt==1)
{
TA0CTL |= TACLR; // Clearing timerA Register
P1DIR |= BIT0;
P1OUT |= BIT0; // LED is turned ON
TA0CCTL0 |= CCIE; // TACCR0 interrupt enabled
TA0CTL |= TASSEL__SMCLK | ID_3 | MC__UP ; // SMCLK, continuous mode
while(timerflag==0);
timerflag=0;
P1OUT &= ~BIT0; // LED is turned OFF
TA0CCTL0 &= ~CCIE; // TACCR0 interrupt Disabled
TA0CTL &= ~MC__UP;
}
}
void uart_init (void)
{
// Configure UART pins
P1SEL0 |= BIT4 | BIT5; // set 2-UART pin as second function
// Configure UART
UCA0CTLW0 |= UCSWRST; // Put eUSCI in reset
UCA0CTLW0 |= UCSSEL__SMCLK; // Chose SMCLK as clock source
// Baud Rate calculation for 9600 with SMCLK (1MHz)
// 1000000/9600 = 104.16
// 1000000/9600 - INT(1000000/9600)=0.16
// UCBRSx value = 0x11 (See UG)
UCA0BR0 = 104;
UCA0MCTLW = 0x1100;
UCA0BR1 = 0;
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
}
bool uart_send_byte (char data)
{
uint16_t uart_timeout = UART_TIMEOUT; // load time out value
while((!(UCA0IFG & UCTXIFG))&&(uart_timeout>0))
{
uart_timeout--; // wait till TX interrupt pending
}
if(uart_timeout == 0)
{
return false; // failure if time out
}
UCA0TXBUF = data;
return true; // success otherwise
}
bool uart_send_debug_string (char array[])
{
uint16_t size = strlen(array);
uint16_t index = 0;
for(index=0; index<size; index++)
{
if(!uart_send_byte(array[index])) // send char one by one
{
return false;
}
}
if(!uart_send_byte(CR)) // send carriage return
{
return false;
}
if(!uart_send_byte(LF)) // send line feed for new line
{
return false;
}
return true;
}
void clk_init(void)
{
// Set Ratio and Desired MCLK Frequency and initialize DCO
CS_initFLLSettle(CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ,CS_SMCLK_FLLREF_RATIO);
// Set SMCLK = DCO with frequency divider of 1
CS_initClockSignal(CS_SMCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_MCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);
P1OUT |= BIT1 + BIT2 + BIT4 + BIT5 + BIT3 + BIT7 ;
P1DIR |= BIT1 + BIT2 + BIT4 + BIT5 + BIT3 + BIT7 ;
P2OUT |= BIT0 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7 + BIT3 ;
P2DIR |= BIT0 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7 + BIT3 ;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(RTC_VECTOR)))
#endif
void RTC_ISR (void)
{
switch (__even_in_range(RTCIV,2)){
case 0: break; //No interrupts
case 2: //RTC overflow
Interrupt=1;
__low_power_mode_off_on_exit();
break;
default: break;
}
}
// Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A0 (void)
#else
#error Compiler not supported!
#endif
{
timerflag=1;
}
//******************************************************************************
//
//This is the TIMER1_A3 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER1_A1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(TIMER1_A1_VECTOR)))
#endif
void TIMER1_A1_ISR (void)
{
//Any access, read or write, of the TAIV register automatically resets the
//highest "pending" interrupt flag
switch ( __even_in_range(TA1IV,14) ){
case 0: break; //No interrupt
case 2: break; //CCR1 not used
case 4: break; //CCR2 not used
case 6: break; //CCR3 not used
case 8: break; //CCR4 not used
case 10: break; //CCR5 not used
case 12: break; //CCR6 not used
case 14:
delayflag=1;
break;
default: break;
}
}