/* 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); }