LTC2946 - Wide Range I2C Power, Charge and Energy Monitor
Features
- Rail-to-Rail Input Range: 0V to 100V
- Wide Input Supply Range: 2.7V to 100V
- Shunt Regulator for Supplies >100V
- ΔΣ ADC with Less Than ±0.4% Total Unadjusted Error
- 12-Bit Resolution for Current and Voltages
- ±1% Accurate Power and Energy Measurements
- ±0.6% Accurate Current and Charge Measurements
- Additional ADC Input Monitors an External Voltage
- Internal ±5% or External Time Bases
- Continuous Scan and Snapshot Modes
- Stores Minimum and Maximum Values
- Alerts When Limits Exceeded
- Split SDA Pin Eases Opto-Isolation
- Shutdown Mode with IQ < 40μA
- Available in 4mm × 3mm DFN and 16-Lead MSOP Packages
Typical Application
Description
The LTC®2946 is a rail-to-rail system monitor that measures current, voltage, power, charge and energy. It features an operating range of 2.7V to 100V and includes a shunt regulator for supplies above 100V. The current measurement common mode range of 0V to 100V is independent of the input supply. A 12-bit ADC measures load current, input voltage and an auxiliary external voltage. Load current and internally calculated power are integrated over an external clock or crystal or internal oscillator time base for charge and energy. An accurate time base allows the LTC2946 to provide measurement accuracy of better than ±0.6% for charge and ±1% for power and energy. Minimum and maximum values are stored and an overrange alert with programmable thresholds minimizes the need for software polling. Data is reported via a standard I2C interface.
The LTC2946 I2C interface includes separate data input and output pins for use with standard or opto-isolated I2C connections. The LTC2946-1 has an inverted data output for use with inverting opto-isolator configurations.
Packaging
CAD Symbols and Footprints: The downloadable Zip file below contains the schematic symbol and PCB footprints.
For complete and up to date package information and drawings, please refer to our packaging page
| Part Number | Package | Code | Temp | Package Drawing |
RoHS |
|---|---|---|---|---|---|
| LTC2946CDE-1#PBF | 4x3 DFN-16 | DE | C | 05-08-1732 | Yes |
| LTC2946CDE-1#TRPBF | 4x3 DFN-16 | DE | C | 05-08-1732 | Yes |
| LTC2946CDE#PBF | 4x3 DFN-16 | DE | C | 05-08-1732 | Yes |
| LTC2946CDE#TRPBF | 4x3 DFN-16 | DE | C | 05-08-1732 | Yes |
| LTC2946CMS-1#PBF | MS-16 | MS | C | 05-08-1669 | Yes |
| LTC2946CMS-1#TRPBF | MS-16 | MS | C | 05-08-1669 | Yes |
| LTC2946CMS#PBF | MS-16 | MS | C | 05-08-1669 | Yes |
| LTC2946CMS#TRPBF | MS-16 | MS | C | 05-08-1669 | Yes |
| LTC2946HDE-1#PBF | 4x3 DFN-16 | DE | H | 05-08-1732 | Yes |
| LTC2946HDE-1#TRPBF | 4x3 DFN-16 | DE | H | 05-08-1732 | Yes |
| LTC2946HDE#PBF | 4x3 DFN-16 | DE | H | 05-08-1732 | Yes |
| LTC2946HDE#TRPBF | 4x3 DFN-16 | DE | H | 05-08-1732 | Yes |
| LTC2946HMS-1#PBF | MS-16 | MS | H | 05-08-1669 | Yes |
| LTC2946HMS-1#TRPBF | MS-16 | MS | H | 05-08-1669 | Yes |
| LTC2946HMS#PBF | MS-16 | MS | H | 05-08-1669 | Yes |
| LTC2946HMS#TRPBF | MS-16 | MS | H | 05-08-1669 | Yes |
| LTC2946IDE-1#PBF | 4x3 DFN-16 | DE | I | 05-08-1732 | Yes |
| LTC2946IDE-1#TRPBF | 4x3 DFN-16 | DE | I | 05-08-1732 | Yes |
| LTC2946IDE#PBF | 4x3 DFN-16 | DE | I | 05-08-1732 | Yes |
| LTC2946IDE#TRPBF | 4x3 DFN-16 | DE | I | 05-08-1732 | Yes |
| LTC2946IMS-1#PBF | MS-16 | MS | I | 05-08-1669 | Yes |
| LTC2946IMS-1#TRPBF | MS-16 | MS | I | 05-08-1669 | Yes |
| LTC2946IMS#PBF | MS-16 | MS | I | 05-08-1669 | Yes |
| LTC2946IMS#TRPBF | MS-16 | MS | I | 05-08-1669 | Yes |
| LTC2946MPMS-1#PBF | MS-16 | MS | MP | 05-08-1669 | Yes |
| LTC2946MPMS-1#TRPBF | MS-16 | MS | MP | 05-08-1669 | Yes |
| LTC2946MPMS#PBF | MS-16 | MS | MP | 05-08-1669 | Yes |
| LTC2946MPMS#TRPBF | MS-16 | MS | MP | 05-08-1669 | Yes |
Order Info
- Part numbers ending in PBF are lead free. Solder plated terminal finish (SnPb) versions are non-standard and special terms and conditions and pricing applies if available. Please contact LTC marketing for information.
- Part numbers containing TR or TRM are shipped in tape and reel or 500 unit mini tape and reel, respectively
- Please refer to our general ordering information or the product datasheet for more details
Package Variations and Pricing
sales office or authorized distributor.Demo Boards
Linear Technology offers many demo boards free of charge to qualified customers. Contact your local sales office or distributor to inquire about a demo board. Certain demo boards are also available for sale via credit card on this website. Demo boards are for evaluation purposes only. It remains the customer’s responsibility to verify proper and reliable operation in the actual end application.| Part Number | Description | Price | Documentation |
|---|---|---|---|
| DC2156A | LTC2946 Demo Board | Wide Range I2C Energy Monitor (req. DC590 or DC2026) | $100.00 | |
| Buy Now | |||
Companion Boards
| Part Number | Description | Price | Documentation |
|---|---|---|---|
| DC2026C | Linduino One Isolated USB Demo Board: An Arduino- and QuikEval-Compatible Code Development Platform | $75.00 | |
| DC590B | Isolated USB Serial Controller for Linear Technology QuikEval-Compatible Demo Boards | $50.00 | |
| Buy Now | |||
Applications
- Telecom Infrastructure
- Industrial Equipment
- General Purpose Energy Measurement
People Who Viewed This Product Also Viewed
- LTC2945 - Wide Range I2C Power Monitor
- LTC2983 - Multi-Sensor High Accuracy Digital Temperature Measurement System
- LT4320/LT4320-1 - Ideal Diode Bridge Controller
- LT8705 - 80V VIN and VOUT Synchronous 4-Switch Buck- Boost DC/DC Controller
- LTC4020 - 55V Buck-Boost Multi-Chemistry Battery Charger
- LTC4151 - High Voltage I2C Current and Voltage Monitor
- LTC4364 - Surge Stopper with Ideal Diode
- LT2940 - Power and Current Monitor
- LT3796/LT3796-1 - 100V Constant-Current and Constant-Voltage Controller with Dual Current Sense
- LT3080 - Adjustable 1.1A Single Resistor Low Dropout Regulator
Product Notifications
Please login to your MyLinear account for notifications of datasheet updates, new document releases and LTspice model announcements for your favorite products. If you do not have a MyLinear account you may Sign Up Now.
Forgot your password? Click here.
Need help? Email mylinear@linear.com with questions and comments.
Design Tools
LTspice
LTspice® software is a powerful, fast and free simulation tool, schematic capture and waveform viewer with enhancements and models for improving the simulation of switching regulators. Click here to download LTspice
Models for the following parts are available in LTspice:
LTC2946
Linduino
Linduino is an Arduino compatible platform for developing and distributing firmware libraries and code for SPI and I²C-compatible integrated circuits. The Linduino One board interfaces to more than 300 QuikEval demonstration cards, supporting a variety of product types including analog-to-digital converters (ADCs), digital-to-analog converters (DACs), power monitors, and more. Firmware libraries for individual devices are written in C and designed to be portable to a wide variety of processors and microcontrollers. Each library has a demonstration program that can be uploaded to the Linduino One platform to allow the circuit and software to be quickly and easily verified.
Code
Linduino is Linear Technology's Arduino compatible system for developing and distributing firmware libraries and example code for Linear Technology’s integrated circuits. The code below can be downloaded or copied and pasted into your project. Please visit the Linduino Home Page for demo board, manual and setup information.
This part is Code Supported: There is example code available for this part. The code below may rely on other drivers available in the full library.
Download LTC2946 - DC2156A Linduino.INO File
/*!
DC2156A
LTC2946: 12-Bit Wide Range Power, Charge and Energy Monitor
@verbatim
Setting the Alert Thresholds:
1. Select the Alert option from the main menu.
2. Select the desired Thresholds to be changed. Then enter the minimum and maximum
values.
3. Select the Enable and Disable Alert Option and Enable the desired alerts.
4. Lastly, go back to the main menu and start reading values in Continuous Mode
or Snapshot Mode.
Note: Alerts only respond when conversion is done. Therefore, in continuous
mode the alerts will constantly be updated.
Reading and Clearing an Alert:
1. Select the Alert option from the main menu.
2. Select the Read and Clear Alerts option. This reads all faults that occured
and clears the alerts.
NOTES
Setup:
Set the terminal baud rate to 115200 and select the newline terminator.
Requires a power supply.
Refer to demo manual DC2156A.
USER INPUT DATA FORMAT:
decimal : 1024
hex : 0x400
octal : 02000 (leading 0 "zero")
binary : B10000000000
float : 1024.0
@endverbatim
REVISION HISTORY
$Revision: 2348 $
$Date: 2014-04-14 13:46:45 -0700 (Mon, 14 Apr 2014) $
Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.
The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community. Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/
/*! @file
@ingroup LTC2946
*/
#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "LT_I2C.h"
#include "LT_SPI.h"
#include "UserInterface.h"
#include "QuikEval_EEPROM.h"
#include "LTC2946.h"
#include <Wire.h>
#include <SPI.h>
// Function Declaration
void print_title(); // Print the title block
void print_prompt(); // Print the Prompt
void store_alert_settings(); // Store the alert settings to the EEPROM
int8_t restore_alert_settings(); // Read the alert settings from EEPROM
int8_t menu_1_continuous_mode(uint8_t CTRLA, uint8_t VOLTAGE_SEL, float scale);
int8_t menu_2_snapshot_mode(uint8_t VOLTAGE_SEL, float scale);
int8_t menu_2_snapshot_mode_menu_1_SENSE();
int8_t menu_2_snapshot_mode_menu_2_ADIN(float scale);
int8_t menu_2_snapshot_mode_menu_3_VDD();
int8_t menu_2_snapshot_mode_menu_4_Current();
int8_t menu_3_alert(uint8_t VOLTAGE_SEL, float scale);
int8_t menu_3_alert_menu_1_set_power_alerts(uint8_t VOLTAGE_SEL, float scale);
int8_t menu_3_alert_menu_2_set_current_alerts();
int8_t menu_3_alert_menu_3_set_vin_alerts();
int8_t menu_3_alert_menu_4_set_adin_alerts(float scale);
int8_t menu_3_alert_menu_5_enable_disable_alerts();
int8_t menu_3_alert_menu_6_read_clear_faults();
int8_t menu_4_shutdown(uint8_t &CTRLB, uint8_t &shutdown);
int8_t menu_5_settings(uint8_t &CTRLA, uint8_t &CTRLB, uint8_t &VOLTAGE_SEL, uint8_t &GPIO_CFG, uint8_t &GPIO3_CTRL, float &scale);
int8_t menu_5_settings_menu_1_configure_CTRLA_reg(uint8_t CTRLA, uint8_t VOLTAGE_SEL);
int8_t menu_5_settings_menu_2_configure_CTRLB_reg(uint8_t CTRLB);
int8_t menu_5_settings_menu_3_configure_GPIO(uint8_t GPIO_CFG, uint8_t GPIO3_CTRL);
int8_t menu_6_clear_min_max();
#define CONTINUOUS_MODE_DISPLAY_DELAY 2000 //!< The delay between readings
const float resistor = .02; //!< resistor value on demo board
const float CLK_FREQ = 4E6; //!< CLK Frequency
// LSB Weights
const float LTC2946_ADIN_lsb = 5.001221E-04; //!< Typical ADIN lsb weight in volts
const float LTC2946_DELTA_SENSE_lsb = 2.5006105E-05; //!< Typical Delta lsb weight in volts
const float LTC2946_VIN_lsb = 2.5006105E-02; //!< Typical VIN lsb weight in volts
const float LTC2946_Power_lsb = 6.25305E-07; //!< Typical POWER lsb weight in V^2 VIN_lsb * DELTA_SENSE_lsb
const float LTC2946_ADIN_DELTA_SENSE_lsb = 1.25061E-08; //!< Typical sense lsb weight in V^2 *ADIN_lsb * DELTA_SENSE_lsb
const float LTC2946_INTERNAL_TIME_lsb = 4101.00/250000.00; //!< Internal TimeBase lsb. Use LTC2946_TIME_lsb if an external CLK is used. See Settings menu for how to calculate Time LSB.
static float LTC2946_TIME_lsb = 16.39543E-3; //!< Static variable which is based off of the default clk frequency of 250KHz.
// Error string
const char ack_error[] = "Error: No Acknowledge. Check I2C Address."; //!< Error message
// Global variables
static int8_t demo_board_connected; //!< Set to 1 if the board is connected
static uint8_t alert1_code = 0; //!< Value stored or read from ALERT1 register. Shared between loop() and restore_alert_settings()
static uint8_t alert2_code = 0; //!< Value stored or read from ALERT2 register. Shared between loop() and restore_alert_settings()
static bool internalCLK = true;
//! Initialize Linduino
void setup()
{
char demo_name[] = "DC2156"; // Demo Board Name stored in QuikEval EEPROM
quikeval_I2C_init(); //! Configure the EEPROM I2C port for 100kHz
quikeval_I2C_connect(); //! Connects to main I2C port
Serial.begin(115200); //! Initialize the serial port to the PC
print_title(); //! Print Title
demo_board_connected = discover_demo_board(demo_name);
if(!demo_board_connected){
Serial.println(F("Demo board not detected, will attempt to proceed"));
demo_board_connected = true;
}
if (demo_board_connected)
{
restore_alert_settings();
print_prompt();
}
}
//! Repeats Linduino loop
void loop()
{
int8_t ack = 0; // I2C acknowledge indicator
static uint8_t user_command; // The user input command
static uint8_t CTRLA = LTC2946_CHANNEL_CONFIG_V_C_3|LTC2946_SENSE_PLUS|LTC2946_OFFSET_CAL_EVERY|LTC2946_ADIN_GND; //! Set Control A register to default value.
static uint8_t CTRLB = LTC2946_DISABLE_ALERT_CLEAR<C2946_DISABLE_SHUTDOWN<C2946_DISABLE_CLEARED_ON_READ<C2946_DISABLE_STUCK_BUS_RECOVER<C2946_ENABLE_ACC<C2946_DISABLE_AUTO_RESET; //! Set Control B Register to default value
static uint8_t GPIO_CFG = LTC2946_GPIO1_OUT_LOW |LTC2946_GPIO2_IN_ACC|LTC2946_GPIO3_OUT_ALERT; //! Set GPIO_CFG Register to Default value
static uint8_t GPIO3_CTRL = LTC2946_GPIO3_OUT_HIGH_Z; //! Set GPIO3_CTRL to Default Value
static uint8_t VOLTAGE_SEL = LTC2946_SENSE_PLUS; //! Set Voltage selection to default value.
static uint8_t shutdown = 0; //! Set Shutdown = 1 to put part in shutdown. This is done through menu item 4.
static float scale = 102.4/2/046; //! Stores division ration for resistive divider on ADIN pin. Configured inside "Settings" menu.
if (demo_board_connected) //! Do nothing if the demo board is not connected
{
if (Serial.available()) //! Do nothing if serial is not available
{
user_command = read_int(); //! Read user input command
if (user_command != 'm')
Serial.println(user_command);
Serial.println();
ack = 0;
switch (user_command) //! Prints the appropriate submenu
{
case 1:
ack |= menu_1_continuous_mode(CTRLA, VOLTAGE_SEL, scale); //! Continuous Mode Measurement
break ;
case 2:
ack |= menu_2_snapshot_mode(VOLTAGE_SEL, scale); //! SnapShot Mode Measurement
break;
case 3:
ack |= menu_3_alert(VOLTAGE_SEL, scale); //! Alert and Threshold Menu
break;
case 4:
ack |= menu_4_shutdown(&CTRLB, &shutdown); //! Toggle Shutdown Down Mode
break;
case 5:
menu_5_settings(&CTRLA, &CTRLB, &VOLTAGE_SEL, &GPIO_CFG, &GPIO3_CTRL, &scale); // Settings
break;
case 6:
ack |= menu_6_clear_min_max(); // Clear Min/Max
break;
default:
Serial.println("Incorrect Option");
break;
}
if (ack != 0)
Serial.println(ack_error);
Serial.print(F("*************************"));
print_prompt();
}
}
}
// Function Definitions
//! Print the title block
void print_title()
{
Serial.println(F("\n*****************************************************************"));
Serial.print(F("* DC2156 Demonstration Program *\n"));
Serial.print(F("* *\n"));
Serial.print(F("* This program communicates with the LTC2946 12-Bit Wide Range *\n"));
Serial.print(F("* I2C Energy and Power Monitor found on the DC2156 demo board. *\n"));
Serial.print(F("* Set the baud rate to 115200 and select the newline terminator.*\n"));
Serial.print(F("* *\n"));
Serial.print(F("*****************************************************************\n"));
}
//! Print the Prompt
void print_prompt()
{
Serial.print(F("\n1-Continuous Mode\n"));
Serial.print(F("2-Snapshot Mode\n"));
Serial.print(F("3-Alert and Threshold Menu\n"));
Serial.print(F("4-Toggle Shutdown Mode\n"));
Serial.print(F("5-Settings\n"));
Serial.print(F("6-Clear Min/Max\n\n"));
Serial.print(F("Enter a command: "));
}
//! Continuous Mode.
int8_t menu_1_continuous_mode(uint8_t CTRLA, //!< CTRLA Register sets the mode in which Continious measurements are made. Configured in "Settings" menu.
uint8_t VOLTAGE_SEL, //!< VOLTAGE_SEL variable represents the voltage channel selected. Scaling is done if ADIN channel is selected and resistive dividers are present.
float scale) //!< Stores division ratio for resistive divider on ADIN pin. Configured inside "Settings" menu.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
uint8_t LTC2946_mode;
int8_t ack = 0;
LTC2946_mode = CTRLA; //! Set the configuration of the CTRLA Register.
Serial.println();
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, LTC2946_mode); //! Sets the LTC2946 to continuous mode
//! Measurement Loop. Keeps Measuring until 'm' is pressed.
//! Measurement is done by first reading the adc code and then converting it to the respective value.
do
{
if (VOLTAGE_SEL != LTC2946_ADIN)
{
Serial.print(F("*************************\n\n"));
uint32_t power_code, max_power_code, min_power_code;
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_POWER_MSB2_REG, &power_code);
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_MSB2_REG, &max_power_code);
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_MSB2_REG, &min_power_code);
float power, max_power, min_power; // Store power results
power = LTC2946_code_to_power(power_code, resistor, LTC2946_Power_lsb);
max_power = LTC2946_code_to_power(max_power_code, resistor, LTC2946_Power_lsb);
min_power = LTC2946_code_to_power(min_power_code, resistor, LTC2946_Power_lsb);
Serial.print(F("****Power: "));
Serial.print(power, 4);
Serial.print(F(" W\n"));
Serial.print(F("Max Power: "));
Serial.print(max_power, 4);
Serial.print(F(" W\n"));
Serial.print(F("Min Power: "));
Serial.print(min_power, 4);
Serial.print(F(" W\n"));
}
else
{
Serial.print(F("*************************"));
Serial.println();
Serial.println();
uint32_t power_code, max_power_code, min_power_code;
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_POWER_MSB2_REG, &power_code);
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_MSB2_REG, &max_power_code);
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_MSB2_REG, &min_power_code);
float power, max_power, min_power;
power = LTC2946_code_to_power(power_code, resistor, LTC2946_ADIN_DELTA_SENSE_lsb) * scale;
max_power = LTC2946_code_to_power(max_power_code, resistor, LTC2946_ADIN_DELTA_SENSE_lsb) * scale;
min_power = LTC2946_code_to_power(min_power_code, resistor, LTC2946_ADIN_DELTA_SENSE_lsb) * scale;
Serial.print(F("\n***ADIN Power: "));
Serial.print(power, 4);
Serial.print(F(" W\n"));
Serial.print(F("Max ADIN Power: "));
Serial.print(max_power, 4);
Serial.print(F(" W\n"));
Serial.print(F("Min ADIN Power: "));
Serial.print(min_power, 4);
Serial.print(F(" W\n"));
}
uint16_t current_code, max_current_code, min_current_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_DELTA_SENSE_MSB_REG, ¤t_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_DELTA_SENSE_MSB_REG, &max_current_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_DELTA_SENSE_MSB_REG, &min_current_code);
float current, max_current, min_current;
current = LTC2946_code_to_current(current_code, resistor, LTC2946_DELTA_SENSE_lsb);
max_current = LTC2946_code_to_current(max_current_code, resistor, LTC2946_DELTA_SENSE_lsb);
min_current = LTC2946_code_to_current(min_current_code, resistor, LTC2946_DELTA_SENSE_lsb);
Serial.print(F("\n****Current: "));
Serial.print(current, 4);
Serial.print(F(" A\n"));
Serial.print(F("Max Current: "));
Serial.print(max_current, 4);
Serial.print(F(" A\n"));
Serial.print(F("Min Current: "));
Serial.print(min_current, 4);
Serial.print(F(" A\n"));
uint16_t VIN_code, max_VIN_code, min_VIN_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_VIN_MSB_REG, &VIN_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_VIN_MSB_REG, &max_VIN_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_VIN_MSB_REG, &min_VIN_code);
float VIN, max_VIN, min_VIN;
VIN = LTC2946_VIN_code_to_voltage(VIN_code , LTC2946_VIN_lsb);
max_VIN = LTC2946_VIN_code_to_voltage(max_VIN_code, LTC2946_VIN_lsb);
min_VIN = LTC2946_VIN_code_to_voltage(min_VIN_code, LTC2946_VIN_lsb);
Serial.print(F("\n****VIN: "));
Serial.print(VIN, 4);
Serial.print(F(" V\n"));
Serial.print(F("Max VIN: "));
Serial.print(max_VIN, 4);
Serial.print(F(" V\n"));
Serial.print(F("Min VIN: "));
Serial.print(min_VIN, 4);
Serial.print(F(" V\n"));
uint16_t ADIN_code, max_ADIN_code, min_ADIN_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_ADIN_MSB_REG, &ADIN_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_ADIN_MSB_REG, &max_ADIN_code);
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_ADIN_MSB_REG, &min_ADIN_code);
float ADIN, max_ADIN, min_ADIN;
ADIN = LTC2946_ADIN_code_to_voltage(ADIN_code, LTC2946_ADIN_lsb)*scale;
max_ADIN = LTC2946_ADIN_code_to_voltage(max_ADIN_code, LTC2946_ADIN_lsb)*scale;
min_ADIN = LTC2946_ADIN_code_to_voltage(min_ADIN_code, LTC2946_ADIN_lsb)*scale;
Serial.print(F("\n****ADIN: "));
Serial.print(ADIN, 4);
Serial.print(F(" V\n"));
Serial.print(F("Max ADIN: "));
Serial.print(max_ADIN, 4);
Serial.print(F(" V\n"));
Serial.print(F("Min ADIN: "));
Serial.print(min_ADIN, 4);
Serial.print(F(" V\n"));
uint32_t energy_code;
ack |= LTC2946_read_32_bits(LTC2946_I2C_ADDRESS, LTC2946_ENERGY_MSB3_REG, &energy_code);
uint32_t charge_code;
ack |= LTC2946_read_32_bits(LTC2946_I2C_ADDRESS, LTC2946_CHARGE_MSB3_REG, &charge_code);
uint32_t time_code;
ack |= LTC2946_read_32_bits(LTC2946_I2C_ADDRESS, LTC2946_TIME_COUNTER_MSB3_REG, &time_code);
float energy,charge,time;
if(internalCLK)
{
energy = LTC2946_code_to_energy(energy_code,resistor,LTC2946_Power_lsb, LTC2946_INTERNAL_TIME_lsb);
charge = LTC2946_code_to_coulombs(charge_code,resistor,LTC2946_DELTA_SENSE_lsb, LTC2946_INTERNAL_TIME_lsb);
time = LTC2946_code_to_time(time_code, LTC2946_INTERNAL_TIME_lsb);
}
else
{
energy = LTC2946_code_to_energy(energy_code,resistor,LTC2946_Power_lsb, LTC2946_TIME_lsb);
charge = LTC2946_code_to_coulombs(charge_code,resistor,LTC2946_DELTA_SENSE_lsb, LTC2946_TIME_lsb);
time = LTC2946_code_to_time(time_code, LTC2946_TIME_lsb);
}
Serial.print(F("**********Accumulators**********\n"));
Serial.print(F("\n****Energy: "));
Serial.print(energy, 4);
Serial.print(F(" J\n"));
Serial.print(F("****Charge: "));
Serial.print(charge, 4);
Serial.print(F(" C\n"));
Serial.print(F("****Time: "));
Serial.print(time, 4);
Serial.print(F(" s\n\n"));
Serial.print(F("********************************\n"));
Serial.print(F("m-Main Menu\n\n"));
Serial.flush();
delay(CONTINUOUS_MODE_DISPLAY_DELAY);
}
while (Serial.available() == false);
read_int(); // clears the Serial.available
return(ack);
}
//! Snapshot Mode Menu
int8_t menu_2_snapshot_mode(uint8_t VOLTAGE_SEL, //!< VOLTAGE_SEL variable represents the voltage channel selected. Scaling is done if ADIN channel is selected and resistive dividers are present.
float scale) //!< Stores division ratio for resistive divider on ADIN pin. Configured inside "Settings" menu.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
//! Print submenu
Serial.print(F("*************************\n\n"));
Serial.print(F("Snapshot Mode\n"));
Serial.print(F("1-SENSE+\n"));
Serial.print(F("2-ADIN\n"));
Serial.print(F("3-VDD\n"));
Serial.print(F("4-Current\n"));
Serial.print(F("m-Main Menu\n"));
uint8_t user_command;
do
{
Serial.print(F("\n\nEnter a Command: "));
user_command = read_int();
if (user_command == 'm')
Serial.println("m");
else
{
Serial.println(user_command);
}
if (user_command != 'm')
{
Serial.print(F("*************************\n\n"));
Serial.print(F("Snapshot Mode\n"));
Serial.print(F("1-SENSE+\n"));
Serial.print(F("2-ADIN\n"));
Serial.print(F("3-VDD\n"));
Serial.print(F("4-Current\n"));
Serial.print(F("m-Main Menu\n"));
}
Serial.println();
switch (user_command)
{
case 1: // SENSE+ - Snapshot Mode
ack |= menu_2_snapshot_mode_menu_1_SENSE();
break;
case 2: // VIN - Snapshot Mode
ack |= menu_2_snapshot_mode_menu_2_ADIN(scale);
break;
case 3: // ADIN - Snapshot Mode
ack |= menu_2_snapshot_mode_menu_3_VDD();
break;
case 4: //Current - Snapshot Mode
ack |= menu_2_snapshot_mode_menu_4_Current();
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
if (user_command != 'm')
{
Serial.print(F("*************************\n\n"));
Serial.print(F("Snapshot Mode\n"));
Serial.print(F("1-SENSE+\n"));
Serial.print(F("2-ADIN\n"));
Serial.print(F("3-VDD\n"));
Serial.print(F("4-Current\n"));
Serial.print(F("m-Main Menu\n"));
}
}
while (!((user_command == 'm') || (ack)));
return(ack);
}
//! SENSE+ - Snapshot mode
int8_t menu_2_snapshot_mode_menu_1_SENSE()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
int8_t LTC2946_mode;
LTC2946_mode = LTC2946_CHANNEL_CONFIG_SNAPSHOT | LTC2946_SENSE_PLUS;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, LTC2946_mode);
uint8_t busy;
do
{
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_STATUS2_REG, &busy);
}
while (0x8 & busy);
uint16_t voltage_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_VIN_MSB_REG, &voltage_code);
float voltage;
voltage = LTC2946_VIN_code_to_voltage(voltage_code, LTC2946_VIN_lsb);
Serial.print(F("SENSE+: "));
Serial.print(voltage, 4);
Serial.print(F(" V\n\n"));
return(ack);
}
//! ADIN - Snapshot Mode
int8_t menu_2_snapshot_mode_menu_2_ADIN(float scale)
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
int8_t LTC2946_mode;
LTC2946_mode = LTC2946_CHANNEL_CONFIG_SNAPSHOT | LTC2946_ADIN;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, LTC2946_mode);
uint8_t busy;
do
{
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_STATUS2_REG, &busy);
}
while (0x8 & busy);
uint16_t ADIN_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_ADIN_MSB_REG, &ADIN_code);
float ADIN;
ADIN = LTC2946_ADIN_code_to_voltage(ADIN_code, LTC2946_ADIN_lsb)*scale;
Serial.print(F("ADIN: "));
Serial.print(ADIN, 4);
Serial.print(F(" V\n\n"));
return(ack);
}
//! VDD - Snapshot Mode
int8_t menu_2_snapshot_mode_menu_3_VDD()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
int8_t LTC2946_mode;
LTC2946_mode = LTC2946_CHANNEL_CONFIG_SNAPSHOT | LTC2946_VDD;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, LTC2946_mode);
uint8_t busy;
do
{
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_STATUS2_REG, &busy);
}
while (0x8 & busy);
uint16_t VDD_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_VIN_MSB_REG, &VDD_code);
float VDD;
VDD = LTC2946_VIN_code_to_voltage(VDD_code, LTC2946_VIN_lsb);
Serial.print(F("VDD: "));
Serial.print(VDD, 4);
Serial.print(F(" V\n\n"));
return(ack);
}
//! Current - Snapshot Mode
int8_t menu_2_snapshot_mode_menu_4_Current()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
int8_t LTC2946_mode;
LTC2946_mode = LTC2946_CHANNEL_CONFIG_SNAPSHOT | LTC2946_DELTA_SENSE;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, LTC2946_mode);
uint8_t busy;
do
{
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_STATUS2_REG, &busy); //!< Check to see if conversion is still in process
}
while (0x8 & busy);
uint16_t current_code;
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_DELTA_SENSE_MSB_REG, ¤t_code);
float current;
current = LTC2946_code_to_current(current_code, resistor, LTC2946_DELTA_SENSE_lsb);
Serial.print(F("Current: "));
Serial.print(current, 4);
Serial.print(F(" A\n\n"));
return(ack);
}
//! Alert and Threshold Menu
int8_t menu_3_alert(uint8_t VOLTAGE_SEL, //!< Voltage Selection Variable.
float scale) //!< Stores division ratio for resistive divider on ADIN pin. Configured inside "Settings" menu.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
int8_t user_command;
do
{
//Print Sub-Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Set Power Alert Thresholds\n"));
Serial.print(F("2-Set Current Alert Thresholds\n"));
Serial.print(F("3-Set VIN Alert Thresholds\n"));
Serial.print(F("4-Set ADIN Alert Thresholds\n"));
Serial.print(F("5-Enable and Disable Alerts\n"));
Serial.print(F("6-Read and Clear Alerts\n"));
Serial.print(F("7-Store Alert Settings to EEPROM\n"));
Serial.print(F("m-Main Menu\n\n"));
Serial.print(F("Enter a command: "));
user_command = read_int();
if (user_command == 'm')
Serial.println("m");
else
Serial.println(user_command);
Serial.println();
switch (user_command)
{
case 1:
ack |= menu_3_alert_menu_1_set_power_alerts(VOLTAGE_SEL, scale); // Set Power Alert Thresholds
break;
case 2:
ack |= menu_3_alert_menu_2_set_current_alerts(); // Set Current Alert Thresholds
break;
case 3:
ack |= menu_3_alert_menu_3_set_vin_alerts(); // Set VIN Alert Thresholds
break;
case 4:
ack |= menu_3_alert_menu_4_set_adin_alerts(scale); // Set ADIN Alert Thresholds
break;
case 5:
ack |= menu_3_alert_menu_5_enable_disable_alerts(); // Enable/Disable Alert Menu
break;
case 6:
ack |= menu_3_alert_menu_6_read_clear_faults(); // Read Fault Register
break;
case 7:
// Read current min/max alarm and store to EEPROM
store_alert_settings();
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (!((user_command == 'm') || (ack)));
return(ack);
}
//! Set Power Alert Thresholds
int8_t menu_3_alert_menu_1_set_power_alerts(uint8_t VOLTAGE_SEL, //!< Choose whether power multiplier uses ADIN pin or SENSE pin as voltage input (A0 bit in CONTROL Register A)
float scale) //!< Scale value based on resistive divider on the ADIN pin.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
Serial.print(F("Enter Max Power Threshold:"));
float max_power_threshold;
max_power_threshold = read_float();
Serial.println(max_power_threshold, 4);
int32_t max_power_threshold_code;
if (VOLTAGE_SEL != LTC2946_ADIN)
max_power_threshold_code = (max_power_threshold / LTC2946_Power_lsb) * resistor;
else
max_power_threshold_code = ((1.0/scale)*(max_power_threshold / LTC2946_ADIN_DELTA_SENSE_lsb)) * resistor;
ack |= LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_THRESHOLD_MSB2_REG, max_power_threshold_code);
Serial.print(F("Enter Min Power Threshold:"));
float min_power_threshold;
min_power_threshold = read_float();
Serial.println(min_power_threshold, 4);
int32_t min_power_threshold_code;
if (VOLTAGE_SEL != LTC2946_ADIN)
min_power_threshold_code = (min_power_threshold / LTC2946_Power_lsb) * resistor;
else
min_power_threshold_code = ((1.0/scale)*(min_power_threshold / LTC2946_ADIN_DELTA_SENSE_lsb)) * resistor;
ack |= LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_THRESHOLD_MSB2_REG, min_power_threshold_code);
return(ack);
}
//! Set Current Alert Thresholds
int8_t menu_3_alert_menu_2_set_current_alerts()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
Serial.print(F("Enter Max Current Threshold:"));
float max_current_threshold;
max_current_threshold = read_float();
Serial.println(max_current_threshold, 4);
int32_t max_current_threshold_code;
max_current_threshold_code = (max_current_threshold / LTC2946_DELTA_SENSE_lsb) * resistor;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_DELTA_SENSE_THRESHOLD_MSB_REG, (max_current_threshold_code << 4));
Serial.print(F("Enter Min Current Threshold:"));
float min_current_threshold;
min_current_threshold = read_float();
Serial.println(min_current_threshold, 4);
int32_t min_current_threshold_code;
min_current_threshold_code = (min_current_threshold / LTC2946_DELTA_SENSE_lsb) * resistor;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_DELTA_SENSE_THRESHOLD_MSB_REG, (min_current_threshold_code << 4));
return(ack);
}
//! Set VIN Alert Thresholds
int8_t menu_3_alert_menu_3_set_vin_alerts()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
Serial.print(F("Enter Max VIN Threshold:"));
float max_VIN_threshold;
max_VIN_threshold = read_float();
Serial.println(max_VIN_threshold, 4);
int32_t max_VIN_threshold_code;
max_VIN_threshold_code = max_VIN_threshold / LTC2946_VIN_lsb;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_VIN_THRESHOLD_MSB_REG, (max_VIN_threshold_code << 4));
Serial.print(F("Enter Min VIN Threshold:"));
float min_VIN_threshold;
min_VIN_threshold = read_float();
Serial.println(min_VIN_threshold, 4);
int32_t min_VIN_threshold_code;
min_VIN_threshold_code = min_VIN_threshold / LTC2946_VIN_lsb;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_VIN_THRESHOLD_MSB_REG, (min_VIN_threshold_code << 4));
return(ack);
}
//! Set ADIN Alert Thresholds
int8_t menu_3_alert_menu_4_set_adin_alerts(float scale //!< Scale value based on resistive divider on the ADIN pin.
)
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
Serial.print(F("Enter Max ADIN Threshold:"));
float max_ADIN_threshold;
max_ADIN_threshold = read_float();
Serial.println(max_ADIN_threshold, 4);
int32_t max_ADIN_threshold_code;
max_ADIN_threshold_code = ((1.0/scale)*max_ADIN_threshold) / LTC2946_ADIN_lsb;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_ADIN_THRESHOLD_MSB_REG, (max_ADIN_threshold_code << 4));
Serial.print(F("Enter Min ADIN Threshold:"));
float min_ADIN_threshold;
min_ADIN_threshold = read_float();
Serial.println(min_ADIN_threshold, 4);
int32_t min_ADIN_threshold_code;
min_ADIN_threshold_code = ((1.0/scale)*min_ADIN_threshold) / LTC2946_ADIN_lsb;
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_ADIN_THRESHOLD_MSB_REG, (min_ADIN_threshold_code << 4));
return(ack);
}
//! Enable/Disable Alert Menu
int8_t menu_3_alert_menu_5_enable_disable_alerts()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Enable/Disable ALERT1 Alerts\n"));
Serial.print(F("2-Enable/Disable ALERT2 Alerts\n"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch (user_command)
{
case 1: // Enable/Disable Alerts in ALERT1 Register
ack |= menu_3_alert_menu_5_enable_disable_alerts_menu_1_ALERT1();
break;
case 2: // Enable/Disable Alerts in ALERT2 Register
ack |= menu_3_alert_menu_5_enable_disable_alerts_menu_2_ALERT2();
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
return(ack);
}
//! Enable/Disable Alert in ALERT1 Register
int8_t menu_3_alert_menu_5_enable_disable_alerts_menu_1_ALERT1()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
//Print Sub-Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Enable/Disable Power Alerts\n"));
Serial.print(F("2-Enable/Disable Current Alerts\n"));
Serial.print(F("3-Enable/Disable VIN Alerts\n"));
Serial.print(F("4-Enable/Disable ADIN Alerts\n"));
Serial.print(F("m-Alert Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
if (!(user_command == 0))
{
Serial.print(F("1-Enable, 2-Disable\n"));
}
switch (user_command)
{
case 1:
// ENABLE/Disable Power Alerts
Serial.print(F("Max Power :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MAX_POWER_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MAX_POWER_ALERT;
Serial.print(F("Min Power :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MIN_POWER_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MIN_POWER_ALERT;
break;
case 2:
// ENABLE/Disable Current Alerts
Serial.print(F("Max Current :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MAX_I_SENSE_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MAX_I_SENSE_ALERT;
Serial.print(F("Min Current :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MIN_I_SENSE_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MIN_I_SENSE_ALERT;
break;
case 3:
// ENABLE/Disable VIN Alerts
Serial.print(F("Max VIN :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MAX_VIN_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MAX_VIN_ALERT;
Serial.print(F("Min VIN :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MIN_VIN_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MIN_VIN_ALERT;
break;
case 4:
// ENABLE/Disable ADIN Alerts
Serial.print(F("Max ADIN :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MAX_ADIN_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MAX_ADIN_ALERT;
Serial.print(F("Min ADIN :"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert1_code = alert1_code | LTC2946_ENABLE_MIN_ADIN_ALERT;
else
alert1_code = alert1_code & LTC2946_DISABLE_MIN_ADIN_ALERT;
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_ALERT1_REG, alert1_code);
return(ack);
}
// Enable/Disable alerts in ALERT2 register
int8_t menu_3_alert_menu_5_enable_disable_alerts_menu_2_ALERT2()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
//Print Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Enable/Disable ADC Conversion Alert\n"));
Serial.print(F("2-Enable/Disable GPIO1 Input Alert\n"));
Serial.print(F("3-Enable/Disable GPIO2 Input Alert\n"));
Serial.print(F("4-Enable/Disable Stuck-Bus Timeout Wake-up Alert\n"));
Serial.print(F("5-Enable/Disable Energy Overflow Alert\n"));
Serial.print(F("6-Enable/Disable Charge Overflow Alert\n"));
Serial.print(F("7-Enable/Disable Time Counter Overflow Alert\n"));
Serial.print(F("m-Alert Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
if (!(user_command == 0))
{
Serial.print(F("1-Enable, 2-Disable\n"));
}
switch (user_command)
{
case 1:
// Enable/Disable ADC Conversion Alert
Serial.print(F("ADC Conv Done: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_ADC_DONE_ALERT;
else
alert2_code = alert2_code & ~LTC2946_ENABLE_ADC_DONE_ALERT ;
break;
case 2:
// Enable/Disable GPIO1 Input Alert
Serial.print(F("GPIO1 Input Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_GPIO_1_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_GPIO_1_ALERT;
break;
case 3:
// Enable/Disable GPIO2 Input Alert
Serial.print(F("GPIO2 Input Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_GPIO_2_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_GPIO_2_ALERT;
break;
case 4:
// Enable/Disable Stuck-Bus Timeout Wake-Up Alert
Serial.print(F("Stuck-Bus Timeout Wake-Up Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_STUCK_BUS_WAKE_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_STUCK_BUS_WAKE_ALERT;
break;
case 5:
// Enable/Disable Energy Overflow Alert
Serial.print(F("Energy Overflow Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_ENERGY_OVERFLOW_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_ENERGY_OVERFLOW_ALERT;
break;
case 6:
// Enable/Disable Charge Overflow Alert
Serial.print(F("Charge Overflow Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_CHARGE_OVERFLOW_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_CHARGE_OVERFLOW_ALERT;
break;
case 7:
// Enable/Disable Time Counter Overflow Alert
Serial.print(F("Time Counter Overflow Alert: "));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
alert2_code = alert2_code | LTC2946_ENABLE_COUNTER_OVERFLOW_ALERT;
else
alert2_code = alert2_code & LTC2946_DISABLE_COUNTER_OVERFLOW_ALERT;
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_ALERT2_REG, alert2_code);
return(ack);
}
//! Read Faults and Clear
int8_t menu_3_alert_menu_6_read_clear_faults()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t fault_code = 0;
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_FAULT1_REG, &fault_code);
if (fault_code & 0x80) Serial.print(F("Power Overvalue Fault Occurred\n\n"));
if (fault_code & 0x40) Serial.print(F("Power Undervalue Fault Occurred\n"));
if (fault_code & 0x20) Serial.print(F("Current Overvalue Fault Occurred\n"));
if (fault_code & 0x10) Serial.print(F("Current Undervalue Fault Occurred\n"));
if (fault_code & 0x08) Serial.print(F("VIN Overvalue Fault Occurred\n"));
if (fault_code & 0x04) Serial.print(F("VIN Undervalue Fault Occurred\n"));
if (fault_code & 0x02) Serial.print(F("ADIN Overvalue Fault Occurred\n"));
if (fault_code & 0x01) Serial.print(F("ADIN Undervalue Fault Occurred\n"));
ack |= LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_FAULT2_REG, &fault_code);
if (fault_code & 0x40) Serial.print(F("GPIO1 Input Fault Occurred\n"));
if (fault_code & 0x20) Serial.print(F("GPIO2 Input Fault Occurred\n"));
if (fault_code & 0x10) Serial.print(F("GPIO3 Input Fault Occurred\n"));
if (fault_code & 0x08) Serial.print(F("Stuck-Bus Timeout Fault Occurred\n"));
if (fault_code & 0x04) Serial.print(F("Energy Overflow Fault Occurred\n"));
if (fault_code & 0x02) Serial.print(F("Charge Overflow Fault Occurred\n"));
if (fault_code & 0x01) Serial.print(F("Time Counter Overflow Fault Occurred\n"));
if (!fault_code) Serial.print(F("No Alarms Were Present\n\n"));
else
{
fault_code = 0;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_FAULT1_REG, fault_code);
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_FAULT2_REG, fault_code);
}
return(ack);
}
//! Toggle Shutdown Down Mode
int8_t menu_4_shutdown(uint8_t *CTRLB, uint8_t *shutdown)
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
if(*shutdown == 0)
{
*CTRLB = *CTRLB | LTC2946_ENABLE_SHUTDOWN;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLB_REG, *CTRLB);
*shutdown = 1;
Serial.print(F("LTC2946 Has Been Shutdown\n\n"));
}
else
{
*CTRLB = *CTRLB & LTC2946_DISABLE_SHUTDOWN;
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLB_REG, *CTRLB);
*shutdown = 0;
Serial.print(F("LTC2946 Is No Longer in Shutdown\n\n"));
}
return(ack);
}
//! Change Settings
int8_t menu_5_settings(uint8_t *CTRLA, //!< Local Copy of Configuration in CTRLA Register.
uint8_t *CTRLB, //!< Local Copy of Configuration in CTRLB Register.
uint8_t *VOLTAGE_SEL, //!< Local Copy of Voltage Selection Channel.
uint8_t *GPIO_CFG, //!< Local Copy of GPIO_CFG Register. Allows Configuration of GPIO1 and GPIO2 Pin states.
uint8_t *GPIO3_CTRL, //!< Local Copy of GPIO3_CTRL Register. Allows Configuration of GPIO3 Pin
float *scale) //!< Stores division ratio for resistive divider on ADIN pin.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
//Print Sub Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Configure CTRLA Register\n"));
Serial.print(F("2-Configure CTRLB Register\n"));
Serial.print(F("3-Configure GPIO Pins\n"));
Serial.print(F("4-Set scaling value for ADIN pin\n"));
Serial.print(F("m-Main Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch (user_command)
{
case 1:
ack |= menu_5_settings_menu_1_configure_CTRLA_reg(CTRLA, VOLTAGE_SEL); //Configure CTRLA Register.
break;
case 2:
ack |= menu_5_settings_menu_2_configure_CTRLB_reg(CTRLB); //Configure CTRLB Register.
break;
case 3:
ack |= menu_5_settings_menu_3_configure_GPIO(GPIO_CFG, GPIO3_CTRL); //Configure GPIO pins.
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
return(ack);
}
//! Configure CTRLA Register.
int8_t menu_5_settings_menu_1_configure_CTRLA_reg(uint8_t *CTRLA, //!<Local Copy of CTRLA Register.
uint8_t *VOLTAGE_SEL) //!<Local Copy of VOLTAGE_SEL. Indicates which voltage channel has been selected for power measurement.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
Serial.println(*CTRLA);
do
{
// Print Sub-Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Configure ADIN reference\n"));
Serial.print(F("2-Configure Offset Calibration\n"));
Serial.print(F("3-Configure Voltage Selection\n"));
Serial.print(F("4-Configure Measurement Channel\n"));
Serial.print(F("m-Settings Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch (user_command)
{
case 1:
menu_5_settings_menu_1_configure_CTRLA_reg_menu_1_ADIN_Configuration(CTRLA); //!< Configure the ADIN reference to GND/INTVCC
break;
case 2:
menu_5_settings_menu_1_configure_CTRLA_reg_menu_2_Offset_Configuration(CTRLA); //!< Configure frequency of offset calibration
break;
case 3:
menu_5_settings_menu_1_configure_CTRLA_reg_menu_3_Voltage_Configuration(CTRLA, VOLTAGE_SEL); //!< Select the voltage measurement channel
break;
case 4:
menu_5_settings_menu_1_configure_CTRLA_reg_menu_4_Channel_Configuration(CTRLA); //!< Select duty cycle of measurments and channel configuration.
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, *CTRLA);
return(ack);
}
//! Configure the ADIN reference to GND/INTVCC
void menu_5_settings_menu_1_configure_CTRLA_reg_menu_1_ADIN_Configuration(uint8_t *CTRLA)
{
uint8_t user_command;
//Print Sub-Menu
Serial.print(F("1-ADIN Measured with Respect to INTVCC\n"));
Serial.print(F("2-ADIN Measured with Respect to GND\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if ((user_command > 2) || (user_command < 1))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
{
*CTRLA = *CTRLA & LTC2946_CTRLA_ADIN_MASK;
*CTRLA = *CTRLA | LTC2946_ADIN_INTVCC;
Serial.print(F("CTRLA set to measure ADIN with respect to INTVCC\n"));
}
else
{
*CTRLA = *CTRLA & LTC2946_CTRLA_ADIN_MASK;
*CTRLA = *CTRLA | LTC2946_ADIN_GND;
Serial.print(F("CTRLA set to measure ADIN with respect to GND\n"));
}
}
//! Configure frequency of offset calibration
void menu_5_settings_menu_1_configure_CTRLA_reg_menu_2_Offset_Configuration(uint8_t *CTRLA)
{
uint8_t user_command;
//Print Sub-Menu
Serial.print(F("1-1st powerup or use last calibrated result\n"));
Serial.print(F("2-Once every 128 conversions\n"));
Serial.print(F("3-Once every 16 conversions\n"));
Serial.print(F("4-Every conversion\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
Serial.println(user_command);
switch(user_command)
{
case 1:
*CTRLA = *CTRLA & LTC2946_CTRLA_OFFSET_MASK;
*CTRLA = *CTRLA | LTC2946_OFFSET_CAL_LAST;
Serial.print(F("Offset Calibration set to use last calibrated result\n"));
break;
case 2:
*CTRLA = *CTRLA & LTC2946_CTRLA_OFFSET_MASK;
*CTRLA = *CTRLA | LTC2946_OFFSET_CAL_128;
Serial.print(F("Offset Calibration set to once every 128 conversions\n"));
break;
case 3:
*CTRLA = *CTRLA & LTC2946_CTRLA_OFFSET_MASK;
*CTRLA = *CTRLA | LTC2946_OFFSET_CAL_16;
Serial.print(F("Offset Calibration set to once every 16 conversions\n"));
break;
case 4:
*CTRLA = *CTRLA & LTC2946_CTRLA_OFFSET_MASK;
*CTRLA = *CTRLA | LTC2946_OFFSET_CAL_EVERY;
Serial.print(F("Offset Calibration set to once every conversion\n"));
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
//! Select the voltage measurement channel
void menu_5_settings_menu_1_configure_CTRLA_reg_menu_3_Voltage_Configuration(uint8_t *CTRLA, //!< Local copy of CTRLA register.
uint8_t *VOLTAGE_SEL) //!< Voltage selection variable.
{
uint8_t user_command;
Serial.print(F("1-SENSE+:\n"));
Serial.print(F("2-ADIN:\n"));
Serial.print(F("3-VDD:\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if ((user_command > 3) || (user_command < 0))
user_command = 1;
Serial.println(user_command);
switch(user_command)
{
case 1:
*CTRLA = *CTRLA & LTC2946_CTRLA_VOLTAGE_SEL_MASK;
*CTRLA = *CTRLA | LTC2946_SENSE_PLUS;
*VOLTAGE_SEL = LTC2946_SENSE_PLUS;
Serial.print(F("SENSE+ selected\n"));
break;
case 2:
*CTRLA = *CTRLA & LTC2946_CTRLA_VOLTAGE_SEL_MASK;
*CTRLA = *CTRLA | LTC2946_ADIN;
*VOLTAGE_SEL = LTC2946_ADIN;
Serial.print(F("ADIN selected\n"));
break;
case 3:
*CTRLA = *CTRLA & LTC2946_CTRLA_VOLTAGE_SEL_MASK;
*CTRLA = *CTRLA | LTC2946_VDD;
*VOLTAGE_SEL = LTC2946_VDD;
Serial.print(F("VDD selected\n"));
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
//!Select duty cycle of measurments and channel configuration.
void menu_5_settings_menu_1_configure_CTRLA_reg_menu_4_Channel_Configuration(uint8_t *CTRLA) //!< Local copy of CTRLA Register
{
uint8_t user_command;
//Print Sub-Menu
Serial.print(F("1-Voltage Once Followed by Current Indefinetly\n"));
Serial.print(F("2-ADIN,Voltage, Current at 1/256, 1/256 and 254/256 Duty Cycle, Respectively\n"));
Serial.print(F("3-ADIN,Voltage, Current at 1/32, 1/32 and 30/32 Duty Cycle, Respectively\n"));
Serial.print(F("4-Aleternate ADIN, Voltage and Current Measurement\n"));
Serial.print(F("5-Voltage and Current at 1/128 and 127/128 Duty Cycle, Respectively\n"));
Serial.print(F("6-Voltage and Current at 1/16 and 15/16 Duty Cycle, Respectively\n"));
Serial.print(F("7-Alternate Voltage and Current Measurement\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
Serial.println(user_command);
switch(user_command)
{
Serial.print(F("Selected Mode = "));
case 1:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_V_C;
Serial.print(F("Voltage Once Followed by Current Indefinetly\n"));
break;
case 2:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_A_V_C_1;
Serial.print(F("ADIN,Voltage, Current at 1/256, 1/256 and 254/256 Duty Cycle, Respectively\n"));
break;
case 3:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_A_V_C_2;
Serial.print(F("ADIN,Voltage, Current at 1/32, 1/32 and 30/32 Duty Cycle, Respectively\n"));
break;
case 4:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_A_V_C_3;
Serial.print(F("Aleternate ADIN, Voltage and Current Measurement\n"));
break;
case 5:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_V_C_1;
Serial.print(F("Voltage and Current at 1/128 and 127/128 Duty Cycle, Respectively\n"));
break;
case 6:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_V_C_2;
Serial.print(F("Voltage and Current at 1/16 and 15/16 Duty Cycle, Respectively\n"));
break;
case 7:
*CTRLA = *CTRLA & LTC2946_CTRLA_CHANNEL_CONFIG_MASK;
*CTRLA = *CTRLA | LTC2946_CHANNEL_CONFIG_V_C_3;
Serial.print(F("Alternate Voltage and Current Measurement\n\n"));
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
//!Configure CTRLB Register.
int8_t menu_5_settings_menu_2_configure_CTRLB_reg(uint8_t *CTRLB) //!< Local copy of CTRLB register.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
//Print Sub-Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-Enable/Disable Alert Clear Enable\n"));
Serial.print(F("2-Enable/Disable Shutdown\n"));
Serial.print(F("3-Enable/Disable Clear On Read\n"));
Serial.print(F("4-Enable/Disable Stuck Bus Timeout Auto Wake up\n"));
Serial.print(F("5-Enable/Disable Accumulation\n"));
Serial.print(F("6-Enable/Disable Auto Reset Mode\n"));
Serial.print(F("m-Settings Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch (user_command)
{
case 1:
Serial.print(F("1-Enable, 2-Disable\n"));
// ENABLE/Disable ADIN Alerts
Serial.print(F(" Alert Clear Enable:"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
*CTRLB = *CTRLB | LTC2946_ENABLE_ALERT_CLEAR;
else
*CTRLB = *CTRLB & LTC2946_DISABLE_ALERT_CLEAR;
break;
case 2:
Serial.print(F("1-Enable, 2-Disable\n"));
Serial.print(F(" Shutdown:"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
*CTRLB = *CTRLB | LTC2946_ENABLE_SHUTDOWN;
else
*CTRLB = *CTRLB & LTC2946_DISABLE_SHUTDOWN;
break;
case 3:
Serial.print(F("1-Enable, 2-Disable\n"));
Serial.print(F(" Cleared On Read Control:"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
*CTRLB = *CTRLB | LTC2946_ENABLE_CLEARED_ON_READ;
else
*CTRLB = *CTRLB & LTC2946_DISABLE_CLEARED_ON_READ;
break;
case 4:
Serial.print(F("1-Enable, 2-Disable\n"));
Serial.print(F(" Stuck Bus Timeout Auto Wake Up:"));
user_command = read_int();
if ((user_command > 2) || (user_command < 0))
user_command = 2;
Serial.println(user_command);
if (user_command == 1)
*CTRLB = *CTRLB | LTC2946_ENABLE_STUCK_BUS_RECOVER;
else
*CTRLB = *CTRLB & LTC2946_DISABLE_STUCK_BUS_RECOVER;
break;
case 5:
Serial.print(F("1-Follow ACC State\n"));
Serial.print(F("2-No Accumulate\n"));
Serial.print(F("3-Accumulate\n"));
Serial.print(F("Enter Command:"));
user_command = read_int();
Serial.println(user_command);
switch(user_command)
{
case 1:
*CTRLB = *CTRLB & LTC2946_CTRLB_ACC_MASK;
*CTRLB = *CTRLB | LTC2946_ACC_PIN_CONTROL;
break;
case 2:
*CTRLB = *CTRLB & LTC2946_CTRLB_ACC_MASK;
*CTRLB = *CTRLB | LTC2946_DISABLE_ACC;
break;
case 3:
*CTRLB = *CTRLB & LTC2946_CTRLB_ACC_MASK;
*CTRLB = *CTRLB | LTC2946_ENABLE_ACC;
break;
default:
Serial.println("Incorrect Option");
}
break;
case 6:
Serial.print(F("1-Reset All Registers\n"));
Serial.print(F("2-Reset Accumulator\n"));
Serial.print(F("3-Enable Auto-Reset\n"));
Serial.print(F("4-Disable Auto-Reset\n"));
Serial.print(F("Enter Command:"));
user_command = read_int();
Serial.println(user_command);
switch(user_command)
{
case 1:
*CTRLB = *CTRLB & LTC2946_CTRLB_RESET_MASK;
*CTRLB = *CTRLB | LTC2946_RESET_ALL;
break;
case 2:
*CTRLB = *CTRLB & LTC2946_CTRLB_RESET_MASK;
*CTRLB = *CTRLB | LTC2946_RESET_ACC;
break;
case 3:
*CTRLB = *CTRLB & LTC2946_CTRLB_RESET_MASK;
*CTRLB = *CTRLB | LTC2946_ENABLE_AUTO_RESET;
break;
case 4:
*CTRLB = *CTRLB & LTC2946_CTRLB_RESET_MASK;
*CTRLB = *CTRLB | LTC2946_DISABLE_AUTO_RESET;
break;
default:
Serial.println("Incorrect Option");
}
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
}
while (user_command != 'm');
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLB_REG, *CTRLB);
return(ack);
}
//! Configure GPIO pin States
int8_t menu_5_settings_menu_3_configure_GPIO(uint8_t *GPIO_CFG, //!< Local copy of GPIO_CFG register.
uint8_t *GPIO3_CTRL) //!< Local copy of GPIO3_CTRL register.
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
uint8_t user_command;
do
{
//Print Sub-Menu
Serial.print(F("*************************\n\n"));
Serial.print(F("1-GPIO1 Configure\n"));
Serial.print(F("2-GPIO2 Configure\n"));
Serial.print(F("3-GPIO3 Configure\n"));
Serial.print(F("m-Settings Menu\n\n"));
Serial.print(F("Enter a command:"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch (user_command)
{
case 1: //Configure GPIO1 state
Serial.print(F("1-General Purpose Input, Active High\n"));
Serial.print(F("2-General Purpose Input, Active Low\n"));
Serial.print(F("3-General Purpose Output, Hi-Z\n"));
Serial.print(F("4-General Purpose Output, Pulls Low\n"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch(user_command)
{
case 1:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO1_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO1_IN_ACTIVE_HIGH;
break;
case 2:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO1_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO1_IN_ACTIVE_LOW;
break;
case 3:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO1_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO1_OUT_HIGH_Z;
break;
case 4:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO1_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO1_OUT_LOW;
break;
default:
Serial.println("Incorrect Option");
}
Serial.println(*GPIO_CFG);
break;
case 2: //Configure GPIO2 state
Serial.print(F("1-General Purpose Input, Active High\n"));
Serial.print(F("2-General Purpose Input, Active Low\n"));
Serial.print(F("3-General Purpose Output, Hi-Z\n"));
Serial.print(F("4-General Purpose Output, Pulls Low\n"));
Serial.print(F("5-Accumulate Input\n"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch(user_command)
{
case 1:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO2_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO2_IN_ACTIVE_HIGH;
break;
case 2:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO2_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO2_IN_ACTIVE_LOW;
break;
case 3:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO2_MASK & LTC2946_GPIOCFG_GPIO2_OUT_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO2_OUT_HIGH_Z;
break;
case 4:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO2_MASK & LTC2946_GPIOCFG_GPIO2_OUT_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO2_OUT_LOW;
break;
case 5:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO2_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO2_IN_ACC;
break;
default:
Serial.println("Incorrect Option");
}
Serial.println(*GPIO_CFG);
break;
case 3: //Confugure GPIO3 state
Serial.print(F("1-General Purpose Input, Active High\n"));
Serial.print(F("2-General Purpose Input, Active Low\n"));
Serial.print(F("3-General Purpose Output, Hi-Z\n"));
Serial.print(F("4-General Purpose Output, Pulls Low\n"));
Serial.print(F("5-ALERT/ Output\n"));
user_command = read_int();
if (user_command == 'm')
Serial.println('m');
else
Serial.println(user_command);
switch(user_command)
{
case 1:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO3_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO3_IN_ACTIVE_HIGH;
break;
case 2:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO3_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO3_IN_ACTIVE_LOW;
break;
case 3:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO3_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO3_OUT_REG_42;
*GPIO3_CTRL = *GPIO3_CTRL & LTC2946_GPIO3_CTRL_GPIO3_MASK;
*GPIO3_CTRL = *GPIO3_CTRL | LTC2946_GPIO3_OUT_HIGH_Z;
break;
case 4:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO3_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO3_OUT_REG_42;
*GPIO3_CTRL = *GPIO3_CTRL & LTC2946_GPIO3_CTRL_GPIO3_MASK;
*GPIO3_CTRL = *GPIO3_CTRL | LTC2946_GPIO3_OUT_LOW;
break;
case 5:
*GPIO_CFG = *GPIO_CFG & LTC2946_GPIOCFG_GPIO3_MASK;
*GPIO_CFG = *GPIO_CFG | LTC2946_GPIO3_OUT_ALERT;
break;
default:
Serial.println("Incorrect Option");
}
Serial.println(*GPIO_CFG);
Serial.println(*GPIO3_CTRL);
break;
default:
if (user_command != 'm')
Serial.println("Incorrect Option");
break;
}
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_GPIO_CFG_REG, *GPIO_CFG);
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_GPIO3_CTRL_REG, *GPIO3_CTRL);
}
while (user_command != 'm');
return(ack);
}
//! Select duty cycle of measurments and channel configuration.
void menu_5_settings_menu_4_scaling_for_ADIN(uint8_t *scale) //!< Stores division ratio for resistive divider on ADIN pin.
{
float user_value;
Serial.print(F("Enter desired maximum voltage for ADIN pin measurement\n"));
Serial.print(F("Note: Ensure that you have the proper resistor divider ratio on the ADIN pin for this voltage level\n"));
user_value = read_float();
*scale = user_value/2.048;
Serial.print(user_value);
Serial.print(F("Scale = "));
Serial.print(*scale);
}
//! Clear Min/Max
int8_t menu_6_clear_min_max()
//! @return Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack = 0;
ack |= LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_MSB2_REG, LTC2946_MAX_POWER_MSB2_RESET);
ack |= LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_MSB2_REG, LTC2946_MIN_POWER_MSB2_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_DELTA_SENSE_MSB_REG, LTC2946_MAX_DELTA_SENSE_MSB_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_DELTA_SENSE_MSB_REG, LTC2946_MIN_DELTA_SENSE_MSB_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_VIN_MSB_REG, LTC2946_MAX_VIN_MSB_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_VIN_MSB_REG, LTC2946_MIN_VIN_MSB_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_ADIN_MSB_REG, LTC2946_MAX_ADIN_MSB_RESET);
ack |= LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_ADIN_MSB_REG, LTC2946_MIN_ADIN_MSB_RESET);
Serial.println();
Serial.print(F("Min/Max Cleared.\n\n"));
return(ack);
}
//! Used to manipulate EEPROM data.
union eeprom_data_union
{
struct data_struct_type //! EEPROM data structure
{
int16_t cal_key; //!< The key that keeps track of the calibration
uint8_t alert1; //!< Used to store the ALERT1 settings
uint8_t alert2; //!< Used to store the ALERT2 settings
uint32_t max_power_threshold; //!< Used to store max power alert settings
uint32_t min_power_threshold; //!< Used to store min power alert settings
uint16_t max_delta_sense_thresh; //!< Used to store max delta sense alert settings
uint16_t min_delta_sense_thresh; //!< Used to store min delta sense alert settings
uint16_t max_Vin_thresh; //!< Used to store max Vin alert settings
uint16_t min_Vin_thresh; //!< Used to store min Vin alert settings
uint16_t max_adin_thresh; //!< Used to store adin max alert settings
uint16_t min_adin_thresh; //!< Used to store adin min alert settings
} data_struct; //!< Name of structure
char byte_array[sizeof(data_struct_type)]; //!< Array used to store the structure
};
//! Read the alert settings from EEPROM
int8_t restore_alert_settings()
//! @return Return 1 if successful, 0 if not
{
int16_t cal_key;
// Read the cal key from the EEPROM
eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
if (cal_key == EEPROM_CAL_KEY)
{
// Calibration has been stored, read thresholds
eeprom_data_union eeprom;
eeprom_read_byte_array(EEPROM_I2C_ADDRESS, eeprom.byte_array, EEPROM_CAL_STATUS_ADDRESS, sizeof(eeprom_data_union));
alert1_code = eeprom.data_struct.alert1; // Global variable used to communicate with loop()
alert2_code = eeprom.data_struct.alert2; // Global variable used to communicate with loop()
LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_ALERT1_REG, eeprom.data_struct.alert1);
LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_ALERT1_REG, eeprom.data_struct.alert2);
LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_THRESHOLD_MSB2_REG, eeprom.data_struct.max_power_threshold);
LTC2946_write_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_THRESHOLD_MSB2_REG, eeprom.data_struct.min_power_threshold);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_DELTA_SENSE_THRESHOLD_MSB_REG, eeprom.data_struct.max_delta_sense_thresh);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_DELTA_SENSE_THRESHOLD_MSB_REG, eeprom.data_struct.min_delta_sense_thresh);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_VIN_THRESHOLD_MSB_REG, eeprom.data_struct.max_Vin_thresh);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_VIN_THRESHOLD_MSB_REG, eeprom.data_struct.min_Vin_thresh);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_ADIN_THRESHOLD_MSB_REG, eeprom.data_struct.max_adin_thresh);
LTC2946_write_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_ADIN_THRESHOLD_MSB_REG, eeprom.data_struct.min_adin_thresh);
Serial.println("Alert Settings Restored");
return(1);
}
else
{
Serial.println("Alert Settings not found");
return(0);
}
}
//! Store the alert settings to the EEPROM
void store_alert_settings()
{
eeprom_data_union eeprom;
eeprom.data_struct.cal_key = EEPROM_CAL_KEY;
LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_ALERT1_REG, &eeprom.data_struct.alert1);
LTC2946_read(LTC2946_I2C_ADDRESS, LTC2946_ALERT2_REG, &eeprom.data_struct.alert2);
LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_POWER_THRESHOLD_MSB2_REG, &eeprom.data_struct.max_power_threshold);
LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_POWER_THRESHOLD_MSB2_REG, &eeprom.data_struct.min_power_threshold);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_DELTA_SENSE_THRESHOLD_MSB_REG, &eeprom.data_struct.max_delta_sense_thresh);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_DELTA_SENSE_THRESHOLD_MSB_REG, &eeprom.data_struct.min_delta_sense_thresh);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_VIN_THRESHOLD_MSB_REG, &eeprom.data_struct.max_Vin_thresh);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_VIN_THRESHOLD_MSB_REG, &eeprom.data_struct.min_Vin_thresh);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MAX_ADIN_THRESHOLD_MSB_REG, &eeprom.data_struct.max_adin_thresh);
LTC2946_read_16_bits(LTC2946_I2C_ADDRESS, LTC2946_MIN_ADIN_THRESHOLD_MSB_REG, &eeprom.data_struct.min_adin_thresh);
eeprom_write_byte_array(EEPROM_I2C_ADDRESS, eeprom.byte_array, EEPROM_CAL_STATUS_ADDRESS, sizeof(eeprom_data_union));
Serial.println("Alert Settings Stored to EEPROM");
}
Download LTC2946 Linduino Header File
/*!
LTC2946: 12-Bit Wide Range Power, Charge and Energy Monitor
@verbatim
The LTC®2946 is a rail-to-rail system monitor that measures
current, voltage, power, charge and energy. It features an
operating range of 2.7V to 100V and includes a shunt regulator
for supplies above 100V. The current measurement common mode
range of 0V to 100V is independent of the input supply.
A 12-bit ADC measures load current, input voltage and an
auxiliary external voltage. Load current and internally
calculated power are integrated over an external clock or
crystal or internal oscillator time base for charge and energy.
An accurate time base allows the LTC2946 to provide measurement
accuracy of better than ±0.6% for charge and ±1% for power and
energy. Minimum and maximum values are stored and an overrange
alert with programmable thresholds minimizes the need for software
polling. Data is reported via a standard I2C interface.
Shutdown mode reduces power consumption to 15uA.
I2C DATA FORMAT (MSB FIRST):
Data Out:
Byte #1 Byte #2 Byte #3
START SA6 SA5 SA4 SA3 SA2 SA1 SA0 W SACK X X C5 C4 C3 C2 C1 C0 SACK D7 D6 D5 D4 D3 D2 D1 D0 SACK STOP
Data In:
Byte #1 Byte #2 Byte #3
START SA6 SA5 SA4 SA3 SA2 SA1 SA0 W SACK X X C5 C4 C3 C2 C1 C0 SACK Repeat Start SA6 SA5 SA4 SA3 SA2 SA1 SA0 R SACK
Byte #4 Byte #5
MSB LSB
D15 D14 D13 D12 D11 D10 D9 D8 MACK D7 D6 D5 D4 D3 D2 D1 D0 MNACK STOP
START : I2C Start
Repeat Start: I2c Repeat Start
STOP : I2C Stop
SAx : I2C Address
SACK : I2C Slave Generated Acknowledge (Active Low)
MACK : I2C Master Generated Acknowledge (Active Low)
MNACK : I2c Master Generated Not Acknowledge
W : I2C Write (0)
R : I2C Read (1)
Cx : Command Code
Dx : Data Bits
X : Don't care
Example Code:
Read power, current, voltage, charge and energy.
CTRLA = LTC2946_CHANNEL_CONFIG_V_C_3|LTC2946_SENSE_PLUS|LTC2946_OFFSET_CAL_EVERY|LTC2946_ADIN_GND; //! Set Control A register to default value in continuous mode
ack |= LTC2946_write(LTC2946_I2C_ADDRESS, LTC2946_CTRLA_REG, CTRLA); //! Sets the LTC2946 to continuous mode
resistor = .02; // Resistor Value On Demo Board
ack |= LTC2946_read_24_bits(LTC2946_I2C_ADDRESS, LTC2946_POWER_MSB2_REG, &power_code); // Reads the ADC registers that contains V^2
power = LTC2946_code_to_power(power_code, resistor, LTC2946_Power_lsb); // Calculates power from power code, resistor value and power lsb
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_DELTA_SENSE_MSB_REG, ¤t_code); // Reads the voltage code across sense resistor
current = LTC2946_code_to_current(current_code, resistor, LTC2946_DELTA_SENSE_lsb); // Calculates current from current code, resistor value and current lsb
ack |= LTC2946_read_12_bits(LTC2946_I2C_ADDRESS, LTC2946_VIN_MSB_REG, &VIN_code); // Reads VIN voltage code
VIN = LTC2946_VIN_code_to_voltage(VIN_code, LTC2946_VIN_lsb); // Calculates VIN voltage from VIN code and lsb
ack |= LTC2946_read_32_bits(LTC2946_I2C_ADDRESS, LTC2946_ENERGY_MSB3_REG, &energy_code); // Reads energy code
energy = LTC2946_code_to_energy(energy_code,resistor,LTC2946_Power_lsb, LTC2946_INTERNAL_TIME_lsb); //Calculates Energy in Joules from energy_code, resistor, power lsb and time lsb
ack |= LTC2946_read_32_bits(LTC2946_I2C_ADDRESS, LTC2946_CHARGE_MSB3_REG, &charge_code); // Reads charge code
charge = LTC2946_code_to_coulombs(charge_code,resistor,LTC2946_DELTA_SENSE_lsb, LTC2946_INTERNAL_TIME_lsb); //Calculates charge in coulombs from charge_code, resistor, current lsb and time lsb
@endverbatim
http://www.linear.com/product/LTC2946
http://www.linear.com/product/ltc2946#demoboards
REVISION HISTORY
$Revision: 2348 $
$Date: 2014-04-14 13:46:45 -0700 (Mon, 14 Apr 2014) $
Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.
The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community. Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/
/*! @file
@ingroup LTC2946
Header for LTC2946: 12-Bit Wide Range Power, Charge and Energy Monitor
*/
#ifndef LTC2946_H
#define LTC2946_H
#include <Wire.h>
//! Use table to select address
/*!
| LTC2946 I2C Address Assignment | Value | AD1 | AD2 |
| :-------------------------------- | :---: | :------: | :------: |
| LTC2946_I2C_ADDRESS | 0x67 | High | Low |
| LTC2946_I2C_ADDRESS | 0x68 | Float | High |
| LTC2946_I2C_ADDRESS | 0x69 | High | High |
| LTC2946_I2C_ADDRESS | 0x6A | Float | Float |
| LTC2946_I2C_ADDRESS | 0x6B | Float | Low |
| LTC2946_I2C_ADDRESS | 0x6C | Low | High |
| LTC2946_I2C_ADDRESS | 0x6D | High | Float |
| LTC2946_I2C_ADDRESS | 0x6E | Low | Float |
| LTC2946_I2C_ADDRESS | 0x6F | Low | Low |
| | | | |
| LTC2946_I2C_MASS_WRITE | 0xCC | X | X |
| LTC2946_I2C_ALERT_RESPONSE | 0x19 | X | X |
*/
/*! @name LTC2946 I2C Address Assignments
@{ */
// Address Choices:
// To choose an address, comment out all options except the
// configuration on the demo board.
// Address assignment
// LTC2946 I2C Address // AD1 AD0
// #define LTC2946_I2C_ADDRESS 0x67 // High Low
// #define LTC2946_I2C_ADDRESS 0x68 // Float High
// #define LTC2946_I2C_ADDRESS 0x69 // High High
// #define LTC2946_I2C_ADDRESS 0x6A // Float Float
// #define LTC2946_I2C_ADDRESS 0x6B // Float Low
// #define LTC2946_I2C_ADDRESS 0x6C // Low High
// #define LTC2946_I2C_ADDRESS 0x6D // High Float
// #define LTC2946_I2C_ADDRESS 0x6E // Low Float
#define LTC2946_I2C_ADDRESS 0x6F // Low Low
#define LTC2946_I2C_MASS_WRITE 0xCC
#define LTC2946_I2C_ALERT_RESPONSE 0x19
//! @}
/*!
| Name | Value |
| :------------------------------------------------ | :---: |
| LTC2946_CTRLA_REG | 0x00 |
| LTC2946_CTRLB_REG | 0x01 |
| LTC2946_ALERT1_REG | 0x02 |
| LTC2946_STATUS1_REG | 0x03 |
| LTC2946_FAULT1_REG | 0x04 |
| LTC2946_POWER_MSB2_REG | 0x05 |
| LTC2946_POWER_MSB1_REG | 0x06 |
| LTC2946_POWER_LSB_REG | 0x07 |
| LTC2946_MAX_POWER_MSB2_REG | 0x08 |
| LTC2946_MAX_POWER_MSB1_REG | 0x09 |
| LTC2946_MAX_POWER_LSB_REG | 0x0A |
| LTC2946_MIN_POWER_MSB2_REG | 0x0B |
| LTC2946_MIN_POWER_MSB1_REG | 0x0C |
| LTC2946_MIN_POWER_LSB_REG | 0x0D |
| LTC2946_MAX_POWER_THRESHOLD_MSB2_REG | 0x0E |
| LTC2946_MAX_POWER_THRESHOLD_MSB1_REG | 0x0F |
| LTC2946_MAX_POWER_THRESHOLD_LSB_REG | 0x10 |
| LTC2946_MIN_POWER_THRESHOLD_MSB2_REG | 0x11 |
| LTC2946_MIN_POWER_THRESHOLD_MSB1_REG | 0x12 |
| LTC2946_MIN_POWER_THRESHOLD_LSB_REG | 0x13 |
| LTC2946_DELTA_SENSE_MSB_REG | 0x14 |
| LTC2946_DELTA_SENSE_LSB_REG | 0x15 |
| LTC2946_MAX_DELTA_SENSE_MSB_REG | 0x16 |
| LTC2946_MAX_DELTA_SENSE_LSB_REG | 0x17 |
| LTC2946_MIN_DELTA_SENSE_MSB_REG | 0x18 |
| LTC2946_MIN_DELTA_SENSE_LSB_REG | 0x19 |
| LTC2946_MAX_DELTA_SENSE_THRESHOLD_MSB_REG | 0x1A |
| LTC2946_MAX_DELTA_SENSE_THRESHOLD_LSB_REG | 0x1B |
| LTC2946_MIN_DELTA_SENSE_THRESHOLD_MSB_REG | 0x1C |
| LTC2946_MIN_DELTA_SENSE_THRESHOLD_LSB_REG | 0x1D |
| LTC2946_VIN_MSB_REG | 0x1E |
| LTC2946_VIN_LSB_REG | 0x1F |
| LTC2946_MAX_VIN_MSB_REG | 0x20 |
| LTC2946_MAX_VIN_LSB_REG | 0x21 |
| LTC2946_MIN_VIN_MSB_REG | 0x22 |
| LTC2946_MIN_VIN_LSB_REG | 0x23 |
| LTC2946_MAX_VIN_THRESHOLD_MSB_REG | 0x24 |
| LTC2946_MAX_VIN_THRESHOLD_LSB_REG | 0x25 |
| LTC2946_MIN_VIN_THRESHOLD_MSB_REG | 0x26 |
| LTC2946_MIN_VIN_THRESHOLD_LSB_REG | 0x27 |
| LTC2946_ADIN_MSB_REG | 0x28 |
| LTC2946_ADIN_LSB_REG_REG | 0x29 |
| LTC2946_MAX_ADIN_MSB_REG | 0x2A |
| LTC2946_MAX_ADIN_LSB_REG | 0x2B |
| LTC2946_MIN_ADIN_MSB_REG | 0x2C |
| LTC2946_MIN_ADIN_LSB_REG | 0x2D |
| LTC2946_MAX_ADIN_THRESHOLD_MSB_REG | 0x2E |
| LTC2946_MAX_ADIN_THRESHOLD_LSB_REG | 0x2F |
| LTC2946_MIN_ADIN_THRESHOLD_MSB_REG | 0x30 |
| LTC2946_MIN_ADIN_THRESHOLD_LSB_REG | 0x31 |
| LTC2946_ALERT2_REG | 0x32 |
| LTC2946_GPIO_CFG_REG | 0x33 |
| LTC2946_TIME_COUNTER_MSB3_REG | 0x34 |
| LTC2946_TIME_COUNTER_MSB2_REG | 0x35 |
| LTC2946_TIME_COUNTER_MSB1_REG | 0x36 |
| LTC2946_TIME_COUNTER_LSB_REG | 0x37 |
| LTC2946_CHARGE_MSB3_REG | 0x38 |
| LTC2946_CHARGE_MSB2_REG | 0x39 |
| LTC2946_CHARGE_MSB1_REG | 0x3A |
| LTC2946_CHARGE_LSB_REG | 0x3B |
| LTC2946_ENERGY_MSB3_REG | 0x3C |
| LTC2946_ENERGY_MSB2_REG | 0x3D |
| LTC2946_ENERGY_MSB1_REG | 0x3E |
| LTC2946_ENERGY_LSB_REG | 0x3F |
| LTC2946_STATUS2_REG | 0x40 |
| LTC2946_FAULT2_REG | 0x41 |
| LTC2946_GPIO3_CTRL_REG | 0x42 |
| LTC2946_CLK_DIV_REG | 0x43 |
*/
/*! @name Registers
@{ */
// Registers
#define LTC2946_CTRLA_REG 0x00
#define LTC2946_CTRLB_REG 0x01
#define LTC2946_ALERT1_REG 0x02
#define LTC2946_STATUS1_REG 0x03
#define LTC2946_FAULT1_REG 0x04
#define LTC2946_POWER_MSB2_REG 0x05
#define LTC2946_POWER_MSB1_REG 0x06
#define LTC2946_POWER_LSB_REG 0x07
#define LTC2946_MAX_POWER_MSB2_REG 0x08
#define LTC2946_MAX_POWER_MSB1_REG 0x09
#define LTC2946_MAX_POWER_LSB_REG 0x0A
#define LTC2946_MIN_POWER_MSB2_REG 0x0B
#define LTC2946_MIN_POWER_MSB1_REG 0x0C
#define LTC2946_MIN_POWER_LSB_REG 0x0D
#define LTC2946_MAX_POWER_THRESHOLD_MSB2_REG 0x0E
#define LTC2946_MAX_POWER_THRESHOLD_MSB1_REG 0x0F
#define LTC2946_MAX_POWER_THRESHOLD_LSB_REG 0x10
#define LTC2946_MIN_POWER_THRESHOLD_MSB2_REG 0x11
#define LTC2946_MIN_POWER_THRESHOLD_MSB1_REG 0x12
#define LTC2946_MIN_POWER_THRESHOLD_LSB_REG 0x13
#define LTC2946_DELTA_SENSE_MSB_REG 0x14
#define LTC2946_DELTA_SENSE_LSB_REG 0x15
#define LTC2946_MAX_DELTA_SENSE_MSB_REG 0x16
#define LTC2946_MAX_DELTA_SENSE_LSB_REG 0x17
#define LTC2946_MIN_DELTA_SENSE_MSB_REG 0x18
#define LTC2946_MIN_DELTA_SENSE_LSB_REG 0x19
#define LTC2946_MAX_DELTA_SENSE_THRESHOLD_MSB_REG 0x1A
#define LTC2946_MAX_DELTA_SENSE_THRESHOLD_LSB_REG 0x1B
#define LTC2946_MIN_DELTA_SENSE_THRESHOLD_MSB_REG 0x1C
#define LTC2946_MIN_DELTA_SENSE_THRESHOLD_LSB_REG 0x1D
#define LTC2946_VIN_MSB_REG 0x1E
#define LTC2946_VIN_LSB_REG 0x1F
#define LTC2946_MAX_VIN_MSB_REG 0x20
#define LTC2946_MAX_VIN_LSB_REG 0x21
#define LTC2946_MIN_VIN_MSB_REG 0x22
#define LTC2946_MIN_VIN_LSB_REG 0x23
#define LTC2946_MAX_VIN_THRESHOLD_MSB_REG 0x24
#define LTC2946_MAX_VIN_THRESHOLD_LSB_REG 0x25
#define LTC2946_MIN_VIN_THRESHOLD_MSB_REG 0x26
#define LTC2946_MIN_VIN_THRESHOLD_LSB_REG 0x27
#define LTC2946_ADIN_MSB_REG 0x28
#define LTC2946_ADIN_LSB_REG_REG 0x29
#define LTC2946_MAX_ADIN_MSB_REG 0x2A
#define LTC2946_MAX_ADIN_LSB_REG 0x2B
#define LTC2946_MIN_ADIN_MSB_REG 0x2C
#define LTC2946_MIN_ADIN_LSB_REG 0x2D
#define LTC2946_MAX_ADIN_THRESHOLD_MSB_REG 0x2E
#define LTC2946_MAX_ADIN_THRESHOLD_LSB_REG 0x2F
#define LTC2946_MIN_ADIN_THRESHOLD_MSB_REG 0x30
#define LTC2946_MIN_ADIN_THRESHOLD_LSB_REG 0x31
#define LTC2946_ALERT2_REG 0x32
#define LTC2946_GPIO_CFG_REG 0x33
#define LTC2946_TIME_COUNTER_MSB3_REG 0x34
#define LTC2946_TIME_COUNTER_MSB2_REG 0x35
#define LTC2946_TIME_COUNTER_MSB1_REG 0x36
#define LTC2946_TIME_COUNTER_LSB_REG 0x37
#define LTC2946_CHARGE_MSB3_REG 0x38
#define LTC2946_CHARGE_MSB2_REG 0x39
#define LTC2946_CHARGE_MSB1_REG 0x3A
#define LTC2946_CHARGE_LSB_REG 0x3B
#define LTC2946_ENERGY_MSB3_REG 0x3C
#define LTC2946_ENERGY_MSB2_REG 0x3D
#define LTC2946_ENERGY_MSB1_REG 0x3E
#define LTC2946_ENERGY_LSB_REG 0x3F
#define LTC2946_STATUS2_REG 0x40
#define LTC2946_FAULT2_REG 0x41
#define LTC2946_GPIO3_CTRL_REG 0x42
#define LTC2946_CLK_DIV_REG 0x43
//! @}
/*!
| Voltage Selection Command | Value |
| :------------------------------------| :---: |
| LTC2946_DELTA_SENSE | 0x00 |
| LTC2946_VDD | 0x08 |
| LTC2946_ADIN | 0x10 |
| LTC2946_SENSE_PLUS | 0x18 |
*/
/*! @name Voltage Selection Command
@{ */
// Voltage Selection Command
#define LTC2946_DELTA_SENSE 0x00
#define LTC2946_VDD 0x08
#define LTC2946_ADIN 0x10
#define LTC2946_SENSE_PLUS 0x18
//! @}
/*!
| Command Codes | Value |
| :-------------------------------------------- | :-------: |
| LTC2946_ADIN_INTVCC | 0x80 |
| LTC2946_ADIN_GND | 0x00 |
| LTC2946_OFFSET_CAL_LAST | 0x60 |
| LTC2946_OFFSET_CAL_128 | 0x40 |
| LTC2946_OFFSET_CAL_16 | 0x20 |
| LTC2946_OFFSET_CAL_EVERY | 0x00 |
| LTC2946_CHANNEL_CONFIG_SNAPSHOT | 0x07 |
| LTC2946_CHANNEL_CONFIG_V_C | 0x06 |
| LTC2946_CHANNEL_CONFIG_A_V_C_1 | 0x05 |
| LTC2946_CHANNEL_CONFIG_A_V_C_2 | 0x04 |
| LTC2946_CHANNEL_CONFIG_A_V_C_3 | 0x03 |
| LTC2946_CHANNEL_CONFIG_V_C_1 | 0x02 |
| LTC2946_CHANNEL_CONFIG_V_C_2 | 0x01 |
| LTC2946_CHANNEL_CONFIG_V_C_3 | 0x00 |
| LTC2946_ENABLE_ALERT_CLEAR | 0x80 |
| LTC2946_ENABLE_SHUTDOWN | 0x40 |
| LTC2946_ENABLE_CLEARED_ON_READ | 0x20 |
| LTC2946_ENABLE_STUCK_BUS_RECOVER | 0x10 |
| LTC2946_DISABLE_ALERT_CLEAR | 0x7F |
| LTC2946_DISABLE_SHUTDOWN | 0xBF |
| LTC2946_DISABLE_CLEARED_ON_READ | 0xDF |
| LTC2946_DISABLE_STUCK_BUS_RECOVER | 0xEF |
| LTC2946_ACC_PIN_CONTROL | 0x08 |
| LTC2946_DISABLE_ACC | 0x04 |
| LTC2946_ENABLE_ACC | 0x00 |
| LTC2946_RESET_ALL | 0x03 |
| LTC2946_RESET_ACC | 0x02 |
| LTC2946_ENABLE_AUTO_RESET | 0x01 |
| LTC2946_DISABLE_AUTO_RESET | 0x00 |
| LTC2946_MAX_POWER_MSB2_RESET | 0x00 |
| LTC2946_MIN_POWER_MSB2_RESET | 0xFF |
| LTC2946_MAX_DELTA_SENSE_MSB_RESET | 0x00 |
| LTC2946_MIN_DELTA_SENSE_MSB_RESET | 0xFF |
| LTC2946_MAX_VIN_MSB_RESET | 0x00 |
| LTC2946_MIN_VIN_MSB_RESET | 0xFF |
| LTC2946_MAX_ADIN_MSB_RESET | 0x00 |
| LTC2946_MIN_ADIN_MSB_RESET | 0xFF |
| LTC2946_ENABLE_MAX_POWER_ALERT | 0x80 |
| LTC2946_ENABLE_MIN_POWER_ALERT | 0x40 |
| LTC2946_DISABLE_MAX_POWER_ALERT | 0x7F |
| LTC2946_DISABLE_MIN_POWER_ALERT | 0xBF |
| LTC2946_ENABLE_MAX_I_SENSE_ALERT | 0x20 |
| LTC2946_ENABLE_MIN_I_SENSE_ALERT | 0x10 |
| LTC2946_DISABLE_MAX_I_SENSE_ALERT | 0xDF |
| LTC2946_DISABLE_MIN_I_SENSE_ALERT | 0xEF |
| LTC2946_ENABLE_MAX_VIN_ALERT | 0x08 |
| LTC2946_ENABLE_MIN_VIN_ALERT | 0x04 |
| LTC2946_DISABLE_MAX_VIN_ALERT | 0xF7 |
| LTC2946_DISABLE_MIN_VIN_ALERT | 0xFB |
| LTC2946_ENABLE_MAX_ADIN_ALERT | 0x02 |
| LTC2946_ENABLE_MIN_ADIN_ALERT | 0x01 |
| LTC2946_DISABLE_MAX_ADIN_ALERT | 0xFD |
| LTC2946_DISABLE_MIN_ADIN_ALERT | 0xFE |
| LTC2946_ENABLE_ADC_DONE_ALERT | 0x80 |
| LTC2946_DISABLE_ADC_DONE_ALERT | 0x7F |
| LTC2946_ENABLE_GPIO_1_ALERT | 0x40 |
| LTC2946_DISABLE_GPIO_1_ALERT | 0xBF |
| LTC2946_ENABLE_GPIO_2_ALERT | 0x20 |
| LTC2946_DISABLE_GPIO_2_ALERT | 0xDF |
| LTC2946_ENABLE_STUCK_BUS_WAKE_ALERT | 0x08 |
| LTC2946_DISABLE_STUCK_BUS_WAKE_ALERT | 0xF7 |
| LTC2946_ENABLE_ENERGY_OVERFLOW_ALERT | 0x04 |
| LTC2946_DISABLE_ENERGY_OVERFLOW_ALERT | 0xFB |
| LTC2946_ENABLE_CHARGE_OVERFLOW_ALERT | 0x02 |
| LTC2946_DISABLE_CHARGE_OVERFLOW_ALERT | 0xFD |
| LTC2946_ENABLE_COUNTER_OVERFLOW_ALERT | 0x01 |
| LTC2946_DISABLE_COUNTER_OVERFLOW_ALERT | 0xFE |
| LTC2946_GPIO1_IN_ACTIVE_HIGH | 0xC0 |
| LTC2946_GPIO1_IN_ACTIVE_LOW | 0x80 |
| LTC2946_GPIO1_OUT_HIGH_Z | 0x40 |
| LTC2946_GPIO1_OUT_LOW | 0x00 |
| LTC2946_GPIO2_IN_ACTIVE_HIGH | 0x30 |
| LTC2946_GPIO2_IN_ACTIVE_LOW | 0x20 |
| LTC2946_GPIO2_OUT_HIGH_Z | 0x10 |
| LTC2946_GPIO2_OUT_LOW | 0x12 |
| LTC2946_GPIO2_IN_ACC | 0x00 |
| LTC2946_GPIO3_IN_ACTIVE_HIGH | 0x18 |
| LTC2946_GPIO3_IN_ACTIVE_LOW | 0x10 |
| LTC2946_GPIO3_OUT_REG_42 | 0x04 |
| LTC2946_GPIO3_OUT_ALERT | 0x00 |
| LTC2946_GPIO3_OUT_LOW | 0x40 |
| LTC2946_GPIO3_OUT_HIGH_Z | 0x00 |
| LTC2946_GPIO_ALERT_CLEAR | 0x00 |
*/
/*! @name Command Codes
@{ */
// Command Codes
#define LTC2946_ADIN_INTVCC 0x80
#define LTC2946_ADIN_GND 0x00
#define LTC2946_OFFSET_CAL_LAST 0x60
#define LTC2946_OFFSET_CAL_128 0x40
#define LTC2946_OFFSET_CAL_16 0x20
#define LTC2946_OFFSET_CAL_EVERY 0x00
#define LTC2946_CHANNEL_CONFIG_SNAPSHOT 0x07
#define LTC2946_CHANNEL_CONFIG_V_C 0x06
#define LTC2946_CHANNEL_CONFIG_A_V_C_1 0x05
#define LTC2946_CHANNEL_CONFIG_A_V_C_2 0x04
#define LTC2946_CHANNEL_CONFIG_A_V_C_3 0x03
#define LTC2946_CHANNEL_CONFIG_V_C_1 0x02
#define LTC2946_CHANNEL_CONFIG_V_C_2 0x01
#define LTC2946_CHANNEL_CONFIG_V_C_3 0x00
#define LTC2946_ENABLE_ALERT_CLEAR 0x80
#define LTC2946_ENABLE_SHUTDOWN 0x40
#define LTC2946_ENABLE_CLEARED_ON_READ 0x20
#define LTC2946_ENABLE_STUCK_BUS_RECOVER 0x10
#define LTC2946_DISABLE_ALERT_CLEAR 0x7F
#define LTC2946_DISABLE_SHUTDOWN 0xBF
#define LTC2946_DISABLE_CLEARED_ON_READ 0xDF
#define LTC2946_DISABLE_STUCK_BUS_RECOVER 0xEF
#define LTC2946_ACC_PIN_CONTROL 0x08
#define LTC2946_DISABLE_ACC 0x04
#define LTC2946_ENABLE_ACC 0x00
#define LTC2946_RESET_ALL 0x03
#define LTC2946_RESET_ACC 0x02
#define LTC2946_ENABLE_AUTO_RESET 0x01
#define LTC2946_DISABLE_AUTO_RESET 0x00
#define LTC2946_MAX_POWER_MSB2_RESET 0x00
#define LTC2946_MIN_POWER_MSB2_RESET 0xFF
#define LTC2946_MAX_DELTA_SENSE_MSB_RESET 0x00
#define LTC2946_MIN_DELTA_SENSE_MSB_RESET 0xFF
#define LTC2946_MAX_VIN_MSB_RESET 0x00
#define LTC2946_MIN_VIN_MSB_RESET 0xFF
#define LTC2946_MAX_ADIN_MSB_RESET 0x00
#define LTC2946_MIN_ADIN_MSB_RESET 0xFF
#define LTC2946_ENABLE_MAX_POWER_ALERT 0x80
#define LTC2946_ENABLE_MIN_POWER_ALERT 0x40
#define LTC2946_DISABLE_MAX_POWER_ALERT 0x7F
#define LTC2946_DISABLE_MIN_POWER_ALERT 0xBF
#define LTC2946_ENABLE_MAX_I_SENSE_ALERT 0x20
#define LTC2946_ENABLE_MIN_I_SENSE_ALERT 0x10
#define LTC2946_DISABLE_MAX_I_SENSE_ALERT 0xDF
#define LTC2946_DISABLE_MIN_I_SENSE_ALERT 0xEF
#define LTC2946_ENABLE_MAX_VIN_ALERT 0x08
#define LTC2946_ENABLE_MIN_VIN_ALERT 0x04
#define LTC2946_DISABLE_MAX_VIN_ALERT 0xF7
#define LTC2946_DISABLE_MIN_VIN_ALERT 0xFB
#define LTC2946_ENABLE_MAX_ADIN_ALERT 0x02
#define LTC2946_ENABLE_MIN_ADIN_ALERT 0x01
#define LTC2946_DISABLE_MAX_ADIN_ALERT 0xFD
#define LTC2946_DISABLE_MIN_ADIN_ALERT 0xFE
#define LTC2946_ENABLE_ADC_DONE_ALERT 0x80
#define LTC2946_DISABLE_ADC_DONE_ALERT 0x7F
#define LTC2946_ENABLE_GPIO_1_ALERT 0x40
#define LTC2946_DISABLE_GPIO_1_ALERT 0xBF
#define LTC2946_ENABLE_GPIO_2_ALERT 0x20
#define LTC2946_DISABLE_GPIO_2_ALERT 0xDF
#define LTC2946_ENABLE_STUCK_BUS_WAKE_ALERT 0x08
#define LTC2946_DISABLE_STUCK_BUS_WAKE_ALERT 0xF7
#define LTC2946_ENABLE_ENERGY_OVERFLOW_ALERT 0x04
#define LTC2946_DISABLE_ENERGY_OVERFLOW_ALERT 0xFB
#define LTC2946_ENABLE_CHARGE_OVERFLOW_ALERT 0x02
#define LTC2946_DISABLE_CHARGE_OVERFLOW_ALERT 0xFD
#define LTC2946_ENABLE_COUNTER_OVERFLOW_ALERT 0x01
#define LTC2946_DISABLE_COUNTER_OVERFLOW_ALERT 0xFE
#define LTC2946_GPIO1_IN_ACTIVE_HIGH 0xC0
#define LTC2946_GPIO1_IN_ACTIVE_LOW 0x80
#define LTC2946_GPIO1_OUT_HIGH_Z 0x40
#define LTC2946_GPIO1_OUT_LOW 0x00
#define LTC2946_GPIO2_IN_ACTIVE_HIGH 0x30
#define LTC2946_GPIO2_IN_ACTIVE_LOW 0x20
#define LTC2946_GPIO2_OUT_HIGH_Z 0x10
#define LTC2946_GPIO2_OUT_LOW 0x12
#define LTC2946_GPIO2_IN_ACC 0x00
#define LTC2946_GPIO3_IN_ACTIVE_HIGH 0x0C
#define LTC2946_GPIO3_IN_ACTIVE_LOW 0x08
#define LTC2946_GPIO3_OUT_REG_42 0x04
#define LTC2946_GPIO3_OUT_ALERT 0x00
#define LTC2946_GPIO3_OUT_LOW 0x40
#define LTC2946_GPIO3_OUT_HIGH_Z 0x00
#define LTC2946_GPIO_ALERT_CLEAR 0x00
//! @}
/*!
| Register Mask Command | Value |
| :------------------------------------| :---: |
| LTC2946_CTRLA_ADIN_MASK | 0x7F |
| LTC2946_CTRLA_OFFSET_MASK | 0x9F |
| LTC2946_CTRLA_VOLTAGE_SEL_MASK | 0xE7 |
| LTC2946_CTRLA_CHANNEL_CONFIG_MASK | 0xF8 |
| LTC2946_CTRLB_ACC_MASK | 0xF3 |
| LTC2946_CTRLB_RESET_MASK | 0xFC |
| LTC2946_GPIOCFG_GPIO1_MASK | 0x3F |
| LTC2946_GPIOCFG_GPIO2_MASK | 0xCF |
| LTC2946_GPIOCFG_GPIO3_MASK | 0xF3 |
| LTC2946_GPIOCFG_GPIO2_OUT_MASK | 0xFD |
| LTC2946_GPIO3_CTRL_GPIO3_MASK | 0xBF |
*/
/*! @name Register Mask Command
@{ */
// Register Mask Command
#define LTC2946_CTRLA_ADIN_MASK 0x7F
#define LTC2946_CTRLA_OFFSET_MASK 0x9F
#define LTC2946_CTRLA_VOLTAGE_SEL_MASK 0xE7
#define LTC2946_CTRLA_CHANNEL_CONFIG_MASK 0xF8
#define LTC2946_CTRLB_ACC_MASK 0xF3
#define LTC2946_CTRLB_RESET_MASK 0xFC
#define LTC2946_GPIOCFG_GPIO1_MASK 0x3F
#define LTC2946_GPIOCFG_GPIO2_MASK 0xCF
#define LTC2946_GPIOCFG_GPIO3_MASK 0xF3
#define LTC2946_GPIOCFG_GPIO2_OUT_MASK 0xFD
#define LTC2946_GPIO3_CTRL_GPIO3_MASK 0xBF
//! @}
//! Write an 8-bit code to the LTC2946.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_write(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint8_t code //!< Value that will be written to the register.
);
//! Write a 16-bit code to the LTC2946.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_write_16_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint16_t code //!< Value that will be written to the register.
);
//! Write a 24-bit code to the LTC2946.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_write_24_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint32_t code //!< Value that will be written to the register.
);
//! Write a 32-bit code to the LTC2946.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_write_32_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint32_t code //!< Value that will be written to the register.
);
//! Reads an 8-bit adc_code from LTC2946
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_read(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint8_t *adc_code //!< Value that will be read from the register.
);
//! Reads a 12-bit adc_code from LTC2946
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_read_12_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint16_t *adc_code //!< Value that will be read from the register.
);
//! Reads a 16-bit adc_code from LTC2946
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_read_16_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint16_t *adc_code //!< Value that will be read from the register.
);
//! Reads a 24-bit adc_code from LTC2946
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_read_24_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint32_t *adc_code //!< Value that will be read from the register.
);
//! Reads a 32-bit adc_code from LTC2946
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2946_read_32_bits(uint8_t i2c_address, //!< Register address for the LTC2946
uint8_t adc_command, //!< The "command byte" for the LTC2946
uint32_t *adc_code //!< Value that will be read from the register.
);
//! Calculate the LTC2946 VIN voltage
//! @return Returns the VIN Voltage in Volts
float LTC2946_VIN_code_to_voltage(uint16_t adc_code, //!< The ADC value
float LTC2946_VIN_lsb //!< VIN lsb weight
);
//! Calculate the LTC2946 ADIN voltage
//! @return Returns the ADIN Voltage in Volts
float LTC2946_ADIN_code_to_voltage(uint16_t adc_code, //!< The ADC value
float LTC2946_ADIN_lsb //!< ADIN lsb weight
);
//! Calculate the LTC2946 current with a sense resistor
//! @return The LTC2946 current in Amps
float LTC2946_code_to_current(uint16_t adc_code, //!< The ADC value
float resistor, //!< The resistor value
float LTC2946_DELTA_SENSE_lsb //!< Delta sense lsb weight
);
//! Calculate the LTC2946 power
//! @return The LTC2946 power in Watts
float LTC2946_code_to_power(int32_t adc_code, //!< The ADC value
float resistor, //!< The resistor value
float LTC2946_Power_lsb); //!< Power lsb weight
//! Calculate the LTC2946 energy
//! @return The LTC2946 energy in Joules
float LTC2946_code_to_energy(int32_t adc_code, //!< The ADC value
float resistor, //!< The resistor value
float LTC2946_Power_lsb, //!< Power lsb weight
float LTC2946_TIME_lsb //!< Time lsb weight
);
//! Calculate the LTC2946 coulombs
//! @return The LTC2946 charge in coulombs
float LTC2946_code_to_coulombs(int32_t adc_code, //!< The ADC value
float resistor, //!< The resistor value
float LTC2946_DELTA_SENSE_lsb, //!< Delta sense lsb weight
float LTC2946_Time_lsb //!< Time lsb weight
);
//! Calculate the LTC2946 internal time base
//! @return The internal time base in seconds.
float LTC2946_code_to_time(float time_code, //!< Time adc code
float LTC2946_Time_lsb //!< Time lsb weight
);
#endif // LTC2946_H
/*!
LTC2946: 12-Bit Wide Range Power, Charge and Energy Monitor
@verbatim
The LTC®2946 is a rail-to-rail system monitor that measures
current, voltage, power, charge and energy. It features an
operating range of 2.7V to 100V and includes a shunt regulator
for supplies above 100V. The current measurement common mode
range of 0V to 100V is independent of the input supply.
A 12-bit ADC measures load current, input voltage and an
auxiliary external voltage. Load current and internally
calculated power are integrated over an external clock or
crystal or internal oscillator time base for charge and energy.
An accurate time base allows the LTC2946 to provide measurement
accuracy of better than ±0.6% for charge and ±1% for power and
energy. Minimum and maximum values are stored and an overrange
alert with programmable thresholds minimizes the need for software
polling. Data is reported via a standard I2C interface.
Shutdown mode reduces power consumption to 15uA.
@endverbatim
http://www.linear.com/product/LTC2946
http://www.linear.com/product/ltc2946#demoboards
REVISION HISTORY
$Revision: 2041 $
$Date: 2013-10-15 16:22:28 -0700 (Tue, 15 Oct 2013) $
Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.
The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community. Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/
//! @defgroup LTC2946 LTC2946: 12-Bit Wide Range Power, Charge and Energy Monitor
/*! @file
@ingroup LTC2946
Library for LTC2946 12-Bit Wide Range Power, Charge and Energy Monitor
*/
#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "LT_I2C.h"
#include "LTC2946.h"
#include <Wire.h>
// Write an 8-bit code to the LTC2946.
int8_t LTC2946_write(uint8_t i2c_address, uint8_t adc_command, uint8_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int32_t ack;
ack = i2c_write_byte_data(i2c_address, adc_command, code);
return ack;
}
// Write a 16-bit code to the LTC2946.
int8_t LTC2946_write_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack;
ack = i2c_write_word_data(i2c_address, adc_command, code);
return(ack);
}
// Write a 24-bit code to the LTC2946.
int8_t LTC2946_write_24_bits(uint8_t i2c_address, uint8_t adc_command, uint32_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack;
LT_union_int32_4bytes data;
data.LT_int32 = code;
ack = i2c_write_block_data(i2c_address, adc_command, (uint8_t) 3, data.LT_byte);
return(ack);
}
int8_t LTC2946_write_32_bits(uint8_t i2c_address, uint8_t adc_command, uint32_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack;
LT_union_int32_4bytes data;
data.LT_int32 = code;
ack = i2c_write_block_data(i2c_address, adc_command, (uint8_t) 4, data.LT_byte);
return(ack);
}
// Reads an 8-bit adc_code from LTC2946
int8_t LTC2946_read(uint8_t i2c_address, uint8_t adc_command, uint8_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int32_t ack;
ack = i2c_read_byte_data(i2c_address, adc_command, adc_code);
return ack;
}
// Reads a 12-bit adc_code from LTC2946
int8_t LTC2946_read_12_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
// Use union type defined in Linduino.h to combine two uint8_t's (8-bit unsigned integers) into one uint16_t (unsigned 16-bit integer)
// Then, shift by 4 bits and return in *adc_code
int32_t ack;
ack = i2c_read_word_data(i2c_address, adc_command, adc_code);
*adc_code >>= 4;
return ack;
}
// Reads a 16-bit adc_code from LTC2946
int8_t LTC2946_read_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int32_t ack;
ack = i2c_read_word_data(i2c_address, adc_command, adc_code);
return ack;
}
// Reads a 24-bit adc_code from LTC2946
int8_t LTC2946_read_24_bits(uint8_t i2c_address, uint8_t adc_command, uint32_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack;
LT_union_int32_4bytes data;
ack = i2c_read_block_data(i2c_address, adc_command, (uint8_t)3, data.LT_byte);
*adc_code = 0x0FFFFFF & data.LT_int32;
return(ack);
}
// Reads a 32-bit adc_code from LTC2946
int8_t LTC2946_read_32_bits(uint8_t i2c_address, uint8_t adc_command, uint32_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
int8_t ack;
LT_union_int32_4bytes data;
ack = i2c_read_block_data(i2c_address, adc_command, (uint8_t) 4, data.LT_byte);
*adc_code = 0xFFFFFFFF & data.LT_int32;
return(ack);
}
// Calculate the LTC2946 VIN voltage
float LTC2946_VIN_code_to_voltage(uint16_t adc_code, float LTC2946_VIN_lsb)
// Returns the VIN Voltage in Volts
{
float voltage;
voltage = (float)adc_code*LTC2946_VIN_lsb; //! 1) Calculate voltage from code and lsb
return(voltage);
}
// Calculate the LTC2946 ADIN voltage
float LTC2946_ADIN_code_to_voltage(uint16_t adc_code, float LTC2946_ADIN_lsb)
// Returns the ADIN Voltage in Volts
{
float adc_voltage;
adc_voltage = (float)adc_code*LTC2946_ADIN_lsb; //! 1) Calculate voltage from code and ADIN lsb
return(adc_voltage);
}
// Calculate the LTC2946 current with a sense resistor
float LTC2946_code_to_current(uint16_t adc_code, float resistor, float LTC2946_DELTA_SENSE_lsb)
// Returns the LTC2946 current in Amps
{
float voltage, current;
voltage = (float)adc_code*LTC2946_DELTA_SENSE_lsb; //! 1) Calculate voltage from ADC code and delta sense lsb
current = voltage/resistor; //! 2) Calculate current, I = V/R
return(current);
}
// Calculate the LTC2946 power
float LTC2946_code_to_power(int32_t adc_code, float resistor, float LTC2946_Power_lsb)
// Returns The LTC2946 power in Watts
{
float power;
power = (float)adc_code*LTC2946_Power_lsb/resistor; //! 1) Calculate Power using Power lsb and resistor
return(power);
}
// Calculate the LTC2946 energy
float LTC2946_code_to_energy(int32_t adc_code,float resistor, float LTC2946_Power_lsb, float LTC2946_TIME_lsb)
// Returns the LTC2946 energy in Joules
{
float energy_lsb, energy;
energy_lsb=(float)(LTC2946_Power_lsb/resistor)*65536*LTC2946_TIME_lsb; //! 1) Calculate Energy lsb from Power lsb and Time lsb
energy = adc_code*energy_lsb; //! 2) Calculate Energy using Energy lsb and adc code
return(energy);
}
// Calculate the LTC2946 Coulombs
float LTC2946_code_to_coulombs(int32_t adc_code, float resistor, float LTC2946_DELTA_SENSE_lsb, float LTC2946_TIME_lsb)
// Returns the LTC2946 Coulombs
{
float coulomb_lsb, coulombs;
coulomb_lsb=(float)(LTC2946_DELTA_SENSE_lsb/resistor)*16*LTC2946_TIME_lsb; //! 1) Calculate Coulomb lsb Current lsb and Time lsb
coulombs = adc_code*coulomb_lsb; //! 2) Calculate Coulombs using Coulomb lsb and adc code
return(coulombs);
}
//Calculate the LTC2946 Time in Seconds
float LTC2946_code_to_time(float time_code, float LTC2946_TIME_lsb)
{
float seconds;
seconds = LTC2946_TIME_lsb * time_code;
return seconds;
}
Technical Support
- For immediate technical assistance, contact your local sales office or distributor or call 1-800-4-LINEAR (US customers only) or 408-432-1900.
- For less urgent requests, please complete our Technical Support Request Form. Please allow 2-3 business days for reply.