This repository has been archived on 2025-01-02. You can view files and clone it, but cannot push or open issues or pull requests.
ads1256/lib/ADS1256.cpp

290 lines
6.8 KiB
C++

/*
ADS1256.h - Arduino Library for communication with Texas Instrument ADS1256 ADC
Written by Adien Akhmad, August 2015
Modfified Jan 2019 by Axel Sepulveda for ATMEGA328
*/
#include "ADS1256.h"
#include "Arduino.h"
#include "SPI.h"
ADS1256::ADS1256(float clockspdMhz, float vref, bool useResetPin)
{
// Set DRDY as input
pinMode(pinDRDY, INPUT);
// Set CS as output
pinMode(pinCS, OUTPUT);
if (useResetPin)
{
// set RESETPIN as output
pinMode(pinRST, OUTPUT);
// pull RESETPIN high
pinMode(pinRST, HIGH);
}
// Voltage Reference
_VREF = vref;
// Default conversion factor
_conversionFactor = 1.0;
// Start SPI on a quarter of ADC clock speed
}
void ADS1256::writeRegister(unsigned char reg, unsigned char wdata)
{
CSON();
SPI.transfer(ADS1256_CMD_WREG | reg); // opcode1 Write registers starting from reg
SPI.transfer(0); // opcode2 Write 1+0 registers
SPI.transfer(wdata); // write wdata
delayMicroseconds(1);
CSOFF();
}
unsigned char ADS1256::readRegister(unsigned char reg)
{
unsigned char readValue;
CSON();
SPI.transfer(ADS1256_CMD_RREG | reg); // opcode1 read registers starting from reg
SPI.transfer(0); // opcode2 read 1+0 registers
delayMicroseconds(7); // t6 delay (4*tCLKIN 50*0.13 = 6.5 us)
readValue = SPI.transfer(0); // read registers
delayMicroseconds(1); // t11 delay (4*tCLKIN 4*0.13 = 0.52 us)
CSOFF();
return readValue;
}
void ADS1256::sendCommand(unsigned char reg)
{
CSON();
waitDRDY();
SPI.transfer(reg);
delayMicroseconds(1); // t11 delay (4*tCLKIN 4*0.13 = 0.52 us)
CSOFF();
}
void ADS1256::setConversionFactor(float val) { _conversionFactor = val; }
void ADS1256::readTest()
{
unsigned char _highByte, _midByte, _lowByte;
CSON();
SPI.transfer(ADS1256_CMD_RDATA);
delayMicroseconds(7); // t6 delay (4*tCLKIN 50*0.13 = 6.5 us)
_highByte = SPI.transfer(ADS1256_CMD_WAKEUP);
_midByte = SPI.transfer(ADS1256_CMD_WAKEUP);
_lowByte = SPI.transfer(ADS1256_CMD_WAKEUP);
CSOFF();
}
float ADS1256::readCurrentChannel()
{
CSON();
SPI.transfer(ADS1256_CMD_RDATA);
delayMicroseconds(7); // t6 delay (4*tCLKIN 50*0.13 = 6.5 us)
float adsCode = read_float32();
CSOFF();
return ((adsCode / 0x7FFFFF) * ((2 * _VREF) / (float)_pga)) *
_conversionFactor;
}
// Reads raw ADC data, as 32bit int
long ADS1256::readCurrentChannelRaw()
{
CSON();
SPI.transfer(ADS1256_CMD_RDATA);
delayMicroseconds(7); // t6 delay (4*tCLKIN 50*0.13 = 6.5 us)
long adsCode = read_int32();
CSOFF();
return adsCode;
}
// Call this ONLY after ADS1256_CMD_RDATA command
unsigned long ADS1256::read_uint24()
{
unsigned char _highByte, _midByte, _lowByte;
unsigned long value;
_highByte = SPI.transfer(0);
_midByte = SPI.transfer(0);
_lowByte = SPI.transfer(0);
// Combine all 3-bytes to 24-bit data using byte shifting.
value = ((long)_highByte << 16) + ((long)_midByte << 8) + ((long)_lowByte);
return value;
}
// Call this ONLY after ADS1256_CMD_RDATA command
// Convert the signed 24bit stored in an unsigned 32bit to a signed 32bit
long ADS1256::read_int32()
{
long value = read_uint24();
if (value & 0x00800000)
{ // if the 24 bit value is negative reflect it to 32bit
value |= 0xff000000;
}
return value;
}
// Call this ONLY after ADS1256_CMD_RDATA command
// Cast as a float
float ADS1256::read_float32()
{
long value = read_int32();
return (float)value;
}
// Channel switching for single ended mode. Negative input channel are
// automatically set to AINCOM
void ADS1256::setChannel(byte channel) { setChannel(channel, -1); }
// Channel Switching for differential mode. Use -1 to set input channel to
// AINCOM
void ADS1256::setChannel(byte AIN_P, byte AIN_N)
{
unsigned char MUX_CHANNEL;
unsigned char MUXP;
unsigned char MUXN;
switch (AIN_P)
{
case 0:
MUXP = ADS1256_MUXP_AIN0;
break;
case 1:
MUXP = ADS1256_MUXP_AIN1;
break;
case 2:
MUXP = ADS1256_MUXP_AIN2;
break;
case 3:
MUXP = ADS1256_MUXP_AIN3;
break;
case 4:
MUXP = ADS1256_MUXP_AIN4;
break;
case 5:
MUXP = ADS1256_MUXP_AIN5;
break;
case 6:
MUXP = ADS1256_MUXP_AIN6;
break;
case 7:
MUXP = ADS1256_MUXP_AIN7;
break;
default:
MUXP = ADS1256_MUXP_AINCOM;
}
switch (AIN_N)
{
case 0:
MUXN = ADS1256_MUXN_AIN0;
break;
case 1:
MUXN = ADS1256_MUXN_AIN1;
break;
case 2:
MUXN = ADS1256_MUXN_AIN2;
break;
case 3:
MUXN = ADS1256_MUXN_AIN3;
break;
case 4:
MUXN = ADS1256_MUXN_AIN4;
break;
case 5:
MUXN = ADS1256_MUXN_AIN5;
break;
case 6:
MUXN = ADS1256_MUXN_AIN6;
break;
case 7:
MUXN = ADS1256_MUXN_AIN7;
break;
default:
MUXN = ADS1256_MUXN_AINCOM;
}
MUX_CHANNEL = MUXP | MUXN;
CSON();
writeRegister(ADS1256_RADD_MUX, MUX_CHANNEL);
sendCommand(ADS1256_CMD_SYNC);
sendCommand(ADS1256_CMD_WAKEUP);
CSOFF();
}
/*
Init chip with set datarate and gain and perform self calibration
*/
void ADS1256::begin(unsigned char drate, unsigned char gain, bool buffenable)
{
_pga = 1 << gain;
sendCommand(ADS1256_CMD_SDATAC); // send out ADS1256_CMD_SDATAC command to stop continous reading mode.
writeRegister(ADS1256_RADD_DRATE, drate); // write data rate register
uint8_t bytemask = B00000111;
uint8_t adcon = readRegister(ADS1256_RADD_ADCON);
uint8_t byte2send = (adcon & ~bytemask) | gain;
writeRegister(ADS1256_RADD_ADCON, byte2send);
if (buffenable)
{
uint8_t status = readRegister(ADS1256_RADD_STATUS);
bitSet(status, 1);
writeRegister(ADS1256_RADD_STATUS, status);
}
sendCommand(ADS1256_CMD_SELFCAL); // perform self calibration
waitDRDY();
; // wait ADS1256 to settle after self calibration
}
/*
Init chip with default datarate and gain and perform self calibration
*/
void ADS1256::begin()
{
sendCommand(ADS1256_CMD_SDATAC); // send out ADS1256_CMD_SDATAC command to stop continous reading mode.
uint8_t status = readRegister(ADS1256_RADD_STATUS);
sendCommand(ADS1256_CMD_SELFCAL); // perform self calibration
waitDRDY(); // wait ADS1256 to settle after self calibration
}
/*
Reads and returns STATUS register
*/
uint8_t ADS1256::getStatus()
{
sendCommand(ADS1256_CMD_SDATAC); // send out ADS1256_CMD_SDATAC command to stop continous reading mode.
return readRegister(ADS1256_RADD_STATUS);
}
void ADS1256::CSON()
{
// PORT_CS &= ~(1 << PINDEX_CS);
digitalWrite(pinCS, LOW);
} // digitalWrite(_CS, LOW); }
void ADS1256::CSOFF()
{
digitalWrite(pinCS, HIGH);
// PORT_CS |= (1 << PINDEX_CS);
} // digitalWrite(_CS, HIGH); }
void ADS1256::waitDRDY()
{
// while (PIN_DRDY & (1 << PINDEX_DRDY));
while (digitalRead(pinDRDY))
;
}
boolean ADS1256::isDRDY()
{
return !digitalRead(pinDRDY);
}