Initial commit with testing from load cell
This commit is contained in:
commit
03c08dea12
|
|
@ -0,0 +1,4 @@
|
||||||
|
.pio
|
||||||
|
CMakeListsPrivate.txt
|
||||||
|
cmake-build-*/
|
||||||
|
.idea/
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE
|
||||||
|
# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags
|
||||||
|
#
|
||||||
|
# If you need to override existing CMake configuration or add extra,
|
||||||
|
# please create `CMakeListsUser.txt` in the root of project.
|
||||||
|
# The `CMakeListsUser.txt` will not be overwritten by PlatformIO.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
set(CMAKE_SYSTEM_NAME Generic)
|
||||||
|
set(CMAKE_C_COMPILER_WORKS 1)
|
||||||
|
set(CMAKE_CXX_COMPILER_WORKS 1)
|
||||||
|
|
||||||
|
project("Adc24Bits" C CXX)
|
||||||
|
|
||||||
|
include(CMakeListsPrivate.txt)
|
||||||
|
|
||||||
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsUser.txt)
|
||||||
|
include(CMakeListsUser.txt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
Production ALL
|
||||||
|
COMMAND platformio -c clion run "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
Debug ALL
|
||||||
|
COMMAND platformio -c clion debug "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(Z_DUMMY_TARGET ${SRC_LIST} lib/ltc2499/src/LTC2499.cpp lib/ltc2499/src/LTC2499.h)
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*************************************************************************
|
||||||
|
Title: LTC2493 / LTC2499 library
|
||||||
|
Authors: Nathan D. Holmes <maverick@drgw.net>
|
||||||
|
File: $Id: $
|
||||||
|
License: GNU General Public License v3
|
||||||
|
|
||||||
|
LICENSE:
|
||||||
|
Copyright (C) 2013 Nathan D. Holmes & Michael D. Petersen
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
*************************************************************************
|
||||||
|
|
||||||
|
This library can be used for:
|
||||||
|
LTC2493: 2/4 channel 24bit ADC
|
||||||
|
LTC2499: 8/16 channel 24bit ADC
|
||||||
|
|
||||||
|
This library contains the ADC part of the combined library Ard2499 which contains the libraries for the LTC2499 24bit ADC and the 24AA025E48 EEPROM
|
||||||
|
See the 16-Channel 24-Bit ADC Data Acquisition Shield for Arduino from Iowa Scaled Engineering:
|
||||||
|
* https://www.iascaled.com/store/ARD-LTC2499
|
||||||
|
* GitHub https://github.com/IowaScaledEngineering/ard-ltc2499
|
||||||
|
|
||||||
|
Changelog
|
||||||
|
Version 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "LTC2499.h"
|
||||||
|
|
||||||
|
byte Ltc2499::changeChannel(byte channel)
|
||||||
|
{
|
||||||
|
return(changeChannel(channel, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte Ltc2499::changeChannel(byte channel, bool addStop)
|
||||||
|
{
|
||||||
|
uint8_t config1=0, config2=0, blockingCountdown;
|
||||||
|
|
||||||
|
if (CHAN_TEMPERATURE == channel)
|
||||||
|
{
|
||||||
|
// The temperature channel is fake - it really has to change the config byte in the message
|
||||||
|
currentChannel = CHAN_TEMPERATURE;
|
||||||
|
config1 = 0x80 | _BV(CONFIG1_ENABLE);
|
||||||
|
config2 = _BV(CONFIG2_ENABLE2) | _BV(CONFIG2_IM) | (CONFIG2_CONFBITS & currentConfig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentChannel = CONFIG1_CHANBITS & channel;
|
||||||
|
config1 = 0x80 | _BV(CONFIG1_ENABLE) | (0x1F & currentChannel);
|
||||||
|
config2 = _BV(CONFIG2_ENABLE2) | (CONFIG2_CONFBITS & currentConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no address, error out
|
||||||
|
if(0 == i2cAddr_)
|
||||||
|
return(ERR);
|
||||||
|
|
||||||
|
// Block in 5ms increments for up to 200ms. Given the conversion rate
|
||||||
|
// should be greater than 7.5sps, 200ms is more than we should ever have to
|
||||||
|
// wait.
|
||||||
|
|
||||||
|
blockingCountdown = 40;
|
||||||
|
while(blockingCountdown--)
|
||||||
|
{
|
||||||
|
this->wireInterface->beginTransmission(i2cAddr_);
|
||||||
|
this->wireInterface->write(config1);
|
||||||
|
this->wireInterface->write(config2);
|
||||||
|
if (0 != this->wireInterface->endTransmission(addStop))
|
||||||
|
{
|
||||||
|
if (0 == blockingCountdown)
|
||||||
|
return(ERR);
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte Ltc2499::changeConfiguration(byte config)
|
||||||
|
{
|
||||||
|
currentConfig = CONFIG2_CONFBITS & config;
|
||||||
|
return(changeChannel(currentChannel));
|
||||||
|
}
|
||||||
|
|
||||||
|
long Ltc2499::read()
|
||||||
|
{
|
||||||
|
unsigned long rawValue = readRaw();
|
||||||
|
|
||||||
|
if (RAW_READ_ERROR == rawValue)
|
||||||
|
return(READ_ERROR);
|
||||||
|
|
||||||
|
uint8_t upperByte = 0xFF & (rawValue>>24);
|
||||||
|
switch(upperByte)
|
||||||
|
{
|
||||||
|
case 0xC0:
|
||||||
|
return(OVERRANGE_POSITIVE);
|
||||||
|
case 0x3F:
|
||||||
|
return(OVERRANGE_NEGATIVE);
|
||||||
|
}
|
||||||
|
rawValue = (rawValue & 0x7FFFFFFF)>>6; // Get rid of the sub-LSBs
|
||||||
|
|
||||||
|
if (0x01000000 & rawValue)
|
||||||
|
rawValue |= 0xFF000000;
|
||||||
|
return((long)rawValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float Ltc2499::readVoltage()
|
||||||
|
{
|
||||||
|
long value = read();
|
||||||
|
|
||||||
|
if (OVERRANGE_POSITIVE == value)
|
||||||
|
return(INFINITY);
|
||||||
|
if (OVERRANGE_NEGATIVE == value)
|
||||||
|
return(-1*INFINITY);
|
||||||
|
|
||||||
|
return((value / 16777216.0) * (referenceMillivolts / 2000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float Ltc2499::readVoltageAndChangeChannel(byte nextChannel)
|
||||||
|
{
|
||||||
|
long value = readAndChangeChannel(nextChannel);
|
||||||
|
|
||||||
|
if (OVERRANGE_POSITIVE == value)
|
||||||
|
return(INFINITY);
|
||||||
|
if (OVERRANGE_NEGATIVE == value)
|
||||||
|
return(-1*INFINITY);
|
||||||
|
|
||||||
|
return((value / 16777216.0) * (referenceMillivolts / 2000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
long Ltc2499::readAndChangeChannel(byte nextChannel)
|
||||||
|
{
|
||||||
|
if (SUCCESS != changeChannel(nextChannel, false))
|
||||||
|
{
|
||||||
|
// Run another transmission through just to send out a stop bit
|
||||||
|
this->wireInterface->beginTransmission(i2cAddr_);
|
||||||
|
this->wireInterface->endTransmission((uint8_t)true);
|
||||||
|
return(READ_ERROR);
|
||||||
|
}
|
||||||
|
// Otherwise, we've succeeded and are sitting on a restart condition
|
||||||
|
return(read());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long Ltc2499::readRaw()
|
||||||
|
{
|
||||||
|
unsigned long retval=0;
|
||||||
|
uint8_t blockingCountdown=40;
|
||||||
|
|
||||||
|
if (0 == i2cAddr_)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
// Block in 5ms increments for up to 200ms. Given the conversion rate
|
||||||
|
// should be greater than 7.5sps, 200ms is more than we should ever have to
|
||||||
|
// wait.
|
||||||
|
while(blockingCountdown--)
|
||||||
|
{
|
||||||
|
this->wireInterface->requestFrom((uint8_t)i2cAddr_, (uint8_t)4, (uint8_t)true);
|
||||||
|
// Error occurred, we don't have as many bytes as expected
|
||||||
|
if (this->wireInterface->available() < 4)
|
||||||
|
{
|
||||||
|
if (0 == blockingCountdown)
|
||||||
|
return(RAW_READ_ERROR);
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval |= this->wireInterface->read();
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= this->wireInterface->read();
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= this->wireInterface->read();
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= this->wireInterface->read();
|
||||||
|
|
||||||
|
return(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long Ltc2499::readRawAndChangeChannel(byte nextChannel)
|
||||||
|
{
|
||||||
|
if (SUCCESS != changeChannel(nextChannel, false))
|
||||||
|
{
|
||||||
|
// Run another transmission through just to send out a stop bit
|
||||||
|
this->wireInterface->beginTransmission(i2cAddr_);
|
||||||
|
this->wireInterface->endTransmission((uint8_t)true);
|
||||||
|
return(RAW_READ_ERROR);
|
||||||
|
}
|
||||||
|
// Otherwise, we've succeeded and are sitting on a restart condition
|
||||||
|
return(readRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
float Ltc2499::readTemperature(byte temperatureUnits)
|
||||||
|
{
|
||||||
|
unsigned int tempDK = readTemperatureDeciK();
|
||||||
|
float tempK = (float)tempDK/10.0;
|
||||||
|
switch(temperatureUnits)
|
||||||
|
{
|
||||||
|
case TEMP_K:
|
||||||
|
return(tempK);
|
||||||
|
case TEMP_C:
|
||||||
|
return(tempK - 273.15);
|
||||||
|
case TEMP_F:
|
||||||
|
return(((tempK - 273.15) * 9.0) / 5.0 + 32.0);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Ltc2499::readTemperatureDeciK()
|
||||||
|
{
|
||||||
|
unsigned long readVal = 0;
|
||||||
|
unsigned long tempDK = 0;
|
||||||
|
|
||||||
|
// If we're currently not set for the temperature channel, switch us over
|
||||||
|
// If we are currently set for the temp channel, then that write will have
|
||||||
|
// triggered a conversion, and readRaw will block until it's done
|
||||||
|
if(CHAN_TEMPERATURE != currentChannel)
|
||||||
|
changeChannel(CHAN_TEMPERATURE, true);
|
||||||
|
|
||||||
|
readVal = readRaw();
|
||||||
|
|
||||||
|
if (RAW_READ_ERROR == readVal)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
// Throw away the sub-LSBs
|
||||||
|
readVal >>= 6;
|
||||||
|
|
||||||
|
tempDK = (0x00FFFFFF & readVal);
|
||||||
|
// Divide by 2 for FS = 1/2 VREF
|
||||||
|
// Divide by 1570 (eqn from 2499 datasheet)
|
||||||
|
// Divide by 100 to convert millivolts to decivolts
|
||||||
|
tempDK = (tempDK * (unsigned long)referenceMillivolts) / 314000;
|
||||||
|
|
||||||
|
// tempDK is now the temperature in deci-kelvin
|
||||||
|
return(tempDK);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ltc2499::Ltc2499()
|
||||||
|
{
|
||||||
|
init_status = ERR;
|
||||||
|
// init_status = ERR | EEPROM_ERR;
|
||||||
|
i2cAddr_ = 0;
|
||||||
|
//i2cAddr_eeprom = 0;
|
||||||
|
currentConfig = 0;
|
||||||
|
currentChannel = 0;
|
||||||
|
|
||||||
|
#ifdef ARDUINO_SAM_DUE
|
||||||
|
wireInterface = &Wire1;
|
||||||
|
#else
|
||||||
|
wireInterface = &Wire;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Ltc2499::Ltc2499(TwoWire& wire)
|
||||||
|
{
|
||||||
|
Ltc2499();
|
||||||
|
this->wireInterface = &wire;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte Ltc2499::begin(byte Address, uint16_t referenceMillivolts)
|
||||||
|
{
|
||||||
|
byte retval = 0;
|
||||||
|
byte i;
|
||||||
|
|
||||||
|
init_status = SUCCESS;
|
||||||
|
|
||||||
|
i2cAddr_ = Address;
|
||||||
|
currentChannel = CHAN_DIFF_0P_1N;
|
||||||
|
currentConfig = CONFIG2_60_50HZ_REJ;
|
||||||
|
|
||||||
|
this->wireInterface->beginTransmission(i2cAddr_);
|
||||||
|
this->wireInterface->write(0x80 | _BV(CONFIG1_ENABLE) | (0x1F & currentChannel));
|
||||||
|
this->wireInterface->write(_BV(CONFIG2_ENABLE2) | (0x7F & currentConfig));
|
||||||
|
retval = this->wireInterface->endTransmission(true);
|
||||||
|
// Anything but zero means we couldn't initialize the LTC2499
|
||||||
|
if (0 != retval)
|
||||||
|
{
|
||||||
|
i2cAddr_ = 0;
|
||||||
|
init_status |= ERR;
|
||||||
|
}
|
||||||
|
this->referenceMillivolts = referenceMillivolts;
|
||||||
|
|
||||||
|
return(init_status);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*************************************************************************
|
||||||
|
Title: LTC2493 / LTC2499 library
|
||||||
|
Authors: Nathan D. Holmes <maverick@drgw.net>
|
||||||
|
File: $Id: $
|
||||||
|
License: GNU General Public License v3
|
||||||
|
|
||||||
|
LICENSE:
|
||||||
|
Copyright (C) 2013 Nathan D. Holmes & Michael D. Petersen
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LTC2499_H
|
||||||
|
#define LTC2499_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Wire.h"
|
||||||
|
|
||||||
|
#ifndef _BV
|
||||||
|
#define _BV(a) (1<<(a))
|
||||||
|
#define _UNDEFINE_BV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FAKE_CONFIG1_TEMPERATURE 6
|
||||||
|
#define CONFIG1_ENABLE 5
|
||||||
|
#define CONFIG1_SINGLE_END 4
|
||||||
|
#define CONFIG1_ODD 3
|
||||||
|
#define CONFIG1_A2 2
|
||||||
|
#define CONFIG1_A1 1
|
||||||
|
#define CONFIG1_A0 0
|
||||||
|
|
||||||
|
#define CHAN_DIFF_0P_1N (0)
|
||||||
|
#define CHAN_DIFF_2P_3N (_BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_4P_5N (_BV(CONFIG1_A1))
|
||||||
|
#define CHAN_DIFF_6P_7N (_BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_8P_9N (_BV(CONFIG1_A2))
|
||||||
|
#define CHAN_DIFF_10P_11N (_BV(CONFIG1_A2) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_12P_13N (_BV(CONFIG1_A2) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_DIFF_14P_15N (_BV(CONFIG1_A2) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
|
||||||
|
#define CHAN_DIFF_1P_0N (_BV(CONFIG1_ODD))
|
||||||
|
#define CHAN_DIFF_3P_2N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_5P_4N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_DIFF_7P_6N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_9P_8N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A2))
|
||||||
|
#define CHAN_DIFF_11P_10N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_DIFF_13P_12N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_DIFF_15P_14N (_BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
|
||||||
|
#define CHAN_SINGLE_0P (_BV(CONFIG1_SINGLE_END))
|
||||||
|
#define CHAN_SINGLE_1P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD))
|
||||||
|
#define CHAN_SINGLE_2P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_3P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_4P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_SINGLE_5P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_SINGLE_6P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_7P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_8P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A2))
|
||||||
|
#define CHAN_SINGLE_9P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A2))
|
||||||
|
#define CHAN_SINGLE_10P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A2) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_11P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_12P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_SINGLE_13P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1))
|
||||||
|
#define CHAN_SINGLE_14P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CHAN_SINGLE_15P (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
|
||||||
|
// The temperature channel is actually fake - we manipulate things internally
|
||||||
|
#define CHAN_TEMPERATURE (_BV(FAKE_CONFIG1_TEMPERATURE))
|
||||||
|
|
||||||
|
#define CONFIG2_ENABLE2 7
|
||||||
|
#define CONFIG2_IM 6
|
||||||
|
#define CONFIG2_FA 5
|
||||||
|
#define CONFIG2_FB 4
|
||||||
|
#define CONFIG2_SPD 3
|
||||||
|
|
||||||
|
#define CONFIG2_50HZ_REJ (_BV(CONFIG2_FB))
|
||||||
|
#define CONFIG2_60HZ_REJ (_BV(CONFIG2_FA))
|
||||||
|
#define CONFIG2_60_50HZ_REJ (0)
|
||||||
|
#define CONFIG2_SPEED_2X (_BV(CONFIG2_SPD))
|
||||||
|
|
||||||
|
#define CONFIG1_CHANBITS (_BV(CONFIG1_SINGLE_END) | _BV(CONFIG1_ODD) | _BV(CONFIG1_A2) | _BV(CONFIG1_A1) | _BV(CONFIG1_A0))
|
||||||
|
#define CONFIG2_CONFBITS (_BV(CONFIG2_FA) | _BV(CONFIG2_FB) | _BV(CONFIG2_SPD))
|
||||||
|
|
||||||
|
#define SUCCESS 0
|
||||||
|
#define ERR 1
|
||||||
|
|
||||||
|
#define ADDR_000 0x14
|
||||||
|
#define ADDR_00Z 0x15
|
||||||
|
#define ADDR_001 0x16
|
||||||
|
#define ADDR_0Z0 0x17
|
||||||
|
#define ADDR_0ZZ 0x24
|
||||||
|
#define ADDR_0Z1 0x25
|
||||||
|
#define ADDR_010 0x26
|
||||||
|
#define ADDR_01Z 0x27
|
||||||
|
#define ADDR_011 0x28
|
||||||
|
#define ADDR_Z00 0x35
|
||||||
|
#define ADDR_Z01 0x37
|
||||||
|
#define ADDR_Z0Z 0x36
|
||||||
|
#define ADDR_ZZ0 0x44
|
||||||
|
#define ADDR_ZZZ 0x45
|
||||||
|
#define ADDR_ZZ1 0x46
|
||||||
|
#define ADDR_Z10 0x47
|
||||||
|
#define ADDR_Z1Z 0x54
|
||||||
|
#define ADDR_Z11 0x55
|
||||||
|
#define ADDR_100 0x56
|
||||||
|
#define ADDR_10Z 0x57
|
||||||
|
#define ADDR_101 0x64
|
||||||
|
#define ADDR_1Z0 0x65
|
||||||
|
#define ADDR_1ZZ 0x66
|
||||||
|
#define ADDR_1Z1 0x67
|
||||||
|
#define ADDR_110 0x74
|
||||||
|
#define ADDR_111 0x76
|
||||||
|
#define ADDR_11Z 0x75
|
||||||
|
|
||||||
|
#define TEMP_DEG_F 0x01
|
||||||
|
|
||||||
|
#define TEMP_K 0x00
|
||||||
|
#define TEMP_F 0x01
|
||||||
|
#define TEMP_C 0x02
|
||||||
|
|
||||||
|
#define RAW_READ_ERROR 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define READ_ERROR 0x01000001
|
||||||
|
#define OVERRANGE_POSITIVE 0x01000000
|
||||||
|
#define OVERRANGE_NEGATIVE 0x11000000
|
||||||
|
|
||||||
|
class Ltc2499
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ltc2499();
|
||||||
|
Ltc2499(TwoWire& wire);
|
||||||
|
|
||||||
|
byte begin(byte Address, uint16_t referenceMillivolts = 4096);
|
||||||
|
|
||||||
|
long read(); // 24-bit plus sign
|
||||||
|
long readAndChangeChannel(byte nextChannel); // 24-bit plus sign
|
||||||
|
float readVoltage();
|
||||||
|
float readVoltageAndChangeChannel(byte nextChannel);
|
||||||
|
|
||||||
|
unsigned long readRaw();
|
||||||
|
unsigned long readRawAndChangeChannel(byte nextChannel);
|
||||||
|
|
||||||
|
byte changeChannel(byte channel);
|
||||||
|
byte changeConfiguration(byte config);
|
||||||
|
unsigned int readTemperatureDeciK();
|
||||||
|
float readTemperature(byte temperatureUnits);
|
||||||
|
|
||||||
|
private:
|
||||||
|
byte changeChannel(byte channel, bool addStop);
|
||||||
|
uint8_t init_status;
|
||||||
|
uint8_t i2cAddr_;
|
||||||
|
uint8_t currentConfig;
|
||||||
|
uint8_t currentChannel;
|
||||||
|
uint16_t referenceMillivolts;
|
||||||
|
TwoWire* wireInterface;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:leonardo]
|
||||||
|
platform = atmelavr
|
||||||
|
board = leonardo
|
||||||
|
framework = arduino
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "../lib/ltc2499/src/LTC2499.h"
|
||||||
|
|
||||||
|
Ltc2499 ltc2499;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Wire.begin();
|
||||||
|
byte status = ltc2499.begin(ADDR_111);
|
||||||
|
if (status) {
|
||||||
|
Serial.print("Error LTC2493"); Serial.println(status);
|
||||||
|
while(true);
|
||||||
|
}
|
||||||
|
ltc2499.changeConfiguration(CONFIG2_60_50HZ_REJ);
|
||||||
|
ltc2499.changeChannel(CHAN_DIFF_0P_1N);
|
||||||
|
delay(80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
/*
|
||||||
|
* Connectivity:
|
||||||
|
*
|
||||||
|
* I've got the LTC2499 configured with a 5.0v reference on the testing board we have.
|
||||||
|
* The e+ wire (red) on the load cell is connected to the 3.332v regulator on the Arduino Leonardo
|
||||||
|
* The e- wire (black) on the load cell is connected to ground on the ADC
|
||||||
|
* The s+/- wires are connected to channel 0/1 on the ADC
|
||||||
|
*
|
||||||
|
* Some preliminary testing showed that a 42g Lego RCX motor (the heavy style) came in at 1442 on the ADC.
|
||||||
|
* It seemed accurate to the gram but did drift a bit over time or with load applied then removed.
|
||||||
|
* The more weight applied, the more it drifted, typically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long adc1 = ltc2499.read();
|
||||||
|
long adc2 = ltc2499.read();
|
||||||
|
long adc3 = ltc2499.read();
|
||||||
|
long adc4 = ltc2499.read();
|
||||||
|
long adc5 = ltc2499.read();
|
||||||
|
long adc = long(double(adc1 + adc2 + adc3 + adc4 + adc5)/5.0);
|
||||||
|
|
||||||
|
Serial.print(adc); Serial.print(", ");
|
||||||
|
|
||||||
|
// This is an approximate bits of ADC precision per single gram.
|
||||||
|
double bitsPerGram = 34.35;
|
||||||
|
|
||||||
|
// This is a very rough estimate of the correct value to "zero" the scale to 0.0g
|
||||||
|
// I found it to be accurate to around a gram if you measured quickly, but it did drift based on time and
|
||||||
|
// the weight applied.
|
||||||
|
long zero = 596140;
|
||||||
|
// I've got a negative here but that might be because I connected the wires backwards
|
||||||
|
Serial.print(-double(adc - zero)/bitsPerGram); Serial.println("");
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue