diff --git a/src/ADS1256.cpp b/src/ADS1256.cpp index 3372b47..5c5d5df 100644 --- a/src/ADS1256.cpp +++ b/src/ADS1256.cpp @@ -1,4 +1,4 @@ -//ADS1256 cpp file +// ADS1256 cpp file /* Name: ADS1256.cpp Created: 2022/07/14 @@ -17,750 +17,772 @@ #define convertSigned24BitToLong(value) ((value) & (1l << 23) ? (value) - 0x1000000 : value) -//Constructor -ADS1256::ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYNC_pin, const int8_t CS_pin,float VREF, SPIClass* spi): _spi(spi), - _DRDY_pin(DRDY_pin), _RESET_pin(RESET_pin), _SYNC_pin(SYNC_pin), _CS_pin(CS_pin), _VREF(VREF), _PGA(0) -{ - pinMode(_DRDY_pin, INPUT); - - if(RESET_pin != PIN_UNUSED) - { - pinMode(_RESET_pin, OUTPUT); - } - - if(SYNC_pin != PIN_UNUSED) - { - pinMode(_SYNC_pin, OUTPUT); - } - - if(CS_pin != PIN_UNUSED) - { - pinMode(_CS_pin, OUTPUT); - } - - updateConversionParameter(); -} - -//Initialization +// Constructor +ADS1256::ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYNC_pin, const int8_t CS_pin, float VREF, SPIClass *spi) : _spi(spi), + _DRDY_pin(DRDY_pin), _RESET_pin(RESET_pin), _SYNC_pin(SYNC_pin), _CS_pin(CS_pin), _VREF(VREF), _PGA(0) +{ + pinMode(_DRDY_pin, INPUT); + + if (RESET_pin != PIN_UNUSED) + { + pinMode(_RESET_pin, OUTPUT); + } + + if (SYNC_pin != PIN_UNUSED) + { + pinMode(_SYNC_pin, OUTPUT); + } + + if (CS_pin != PIN_UNUSED) + { + pinMode(_CS_pin, OUTPUT); + } + + updateConversionParameter(); +} + +// Initialization void ADS1256::InitializeADC() -{ - //Chip select LOW - CS_LOW(); - - //We do a manual chip reset on the ADS1256 - Datasheet Page 27/ RESET - if(_RESET_pin != PIN_UNUSED) - { - digitalWrite(_RESET_pin, LOW); - delay(200); - digitalWrite(_RESET_pin, HIGH); //RESET is set to high - delay(1000); - } - - //Sync pin is also treated if it is defined - if(_SYNC_pin != PIN_UNUSED) - { - digitalWrite(_SYNC_pin, HIGH); //RESET is set to high - } - -#ifndef ADS1256_SPI_ALREADY_STARTED //Guard macro to allow external initialization of the SPI - _spi->begin(); +{ + // Chip select LOW + CS_LOW(); + + // We do a manual chip reset on the ADS1256 - Datasheet Page 27/ RESET + if (_RESET_pin != PIN_UNUSED) + { + digitalWrite(_RESET_pin, LOW); + delay(200); + digitalWrite(_RESET_pin, HIGH); // RESET is set to high + delay(1000); + } + + // Sync pin is also treated if it is defined + if (_SYNC_pin != PIN_UNUSED) + { + digitalWrite(_SYNC_pin, HIGH); // RESET is set to high + } + +#ifndef ADS1256_SPI_ALREADY_STARTED // Guard macro to allow external initialization of the SPI + _spi->begin(); #endif - - //Applying arbitrary default values to speed up the starting procedure if the user just want to get quick readouts - //We both pass values to the variables and then send those values to the corresponding registers - delay(200); - - _STATUS = 0b00110110; //BUFEN and ACAL enabled, Order is MSB, rest is read only - writeRegister(STATUS_REG, _STATUS); - delay(200); - - _MUX = 0b00000001; //MUX AIN0+AIN1 - writeRegister(MUX_REG, _MUX); - delay(200); - - _ADCON = 0b00000000; //ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) - writeRegister(ADCON_REG, _ADCON); - delay(200); - - updateConversionParameter(); - - _DRATE = 0b10000010; //100SPS - writeRegister(DRATE_REG, _DRATE); - delay(200); - - sendDirectCommand(0b11110000); //Offset and self-gain calibration - delay(200); - - _isAcquisitionRunning = false; //MCU will be waiting to start a continuous acquisition + + // Applying arbitrary default values to speed up the starting procedure if the user just want to get quick readouts + // We both pass values to the variables and then send those values to the corresponding registers + delay(200); + + _STATUS = 0b00110110; // BUFEN and ACAL enabled, Order is MSB, rest is read only + writeRegister(STATUS_REG, _STATUS); + delay(200); + + _MUX = 0b00000001; // MUX AIN0+AIN1 + writeRegister(MUX_REG, _MUX); + delay(200); + + _ADCON = 0b00000000; // ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) + writeRegister(ADCON_REG, _ADCON); + delay(200); + + updateConversionParameter(); + + _DRATE = 0b10000010; // 100SPS + writeRegister(DRATE_REG, _DRATE); + delay(200); + + sendDirectCommand(0b11110000); // Offset and self-gain calibration + delay(200); + + _isAcquisitionRunning = false; // MCU will be waiting to start a continuous acquisition } void ADS1256::waitForLowDRDY() -{ - while (digitalRead(_DRDY_pin) == HIGH) {} +{ + while (digitalRead(_DRDY_pin) == HIGH) + { + } } void ADS1256::waitForHighDRDY() -{ -#if F_CPU >= 48000000 //Fast MCUs need this protection to wait until DRDY goes high after a conversion - while (digitalRead(_DRDY_pin) == LOW) {} +{ +#if F_CPU >= 48000000 // Fast MCUs need this protection to wait until DRDY goes high after a conversion + while (digitalRead(_DRDY_pin) == LOW) + { + } #endif } -void ADS1256::stopConversion() //Sending SDATAC to stop the continuous conversion -{ - waitForLowDRDY(); //SDATAC should be called after DRDY goes LOW (p35. Figure 33) - _spi->transfer(0b00001111); //Send SDATAC to the ADC - CS_HIGH(); //We finished the command sequence, so we switch it back to HIGH - _spi->endTransaction(); - - _isAcquisitionRunning = false; //Reset to false, so the MCU will be able to start a new conversion +void ADS1256::stopConversion() // Sending SDATAC to stop the continuous conversion +{ + waitForLowDRDY(); // SDATAC should be called after DRDY goes LOW (p35. Figure 33) + _spi->transfer(0b00001111); // Send SDATAC to the ADC + CS_HIGH(); // We finished the command sequence, so we switch it back to HIGH + _spi->endTransaction(); + + _isAcquisitionRunning = false; // Reset to false, so the MCU will be able to start a new conversion } -void ADS1256::setDRATE(uint8_t drate) //Setting DRATE (sampling frequency) -{ - writeRegister(DRATE_REG, drate); - _DRATE = drate; - delay(200); +void ADS1256::setDRATE(uint8_t drate) // Setting DRATE (sampling frequency) +{ + writeRegister(DRATE_REG, drate); + _DRATE = drate; + delay(200); } -void ADS1256::setMUX(uint8_t mux) //Setting MUX (input channel) -{ - writeRegister(MUX_REG, mux); - _MUX = mux; - delay(200); +void ADS1256::setMUX(uint8_t mux) // Setting MUX (input channel) +{ + writeRegister(MUX_REG, mux); + _MUX = mux; + delay(200); } -void ADS1256::setPGA(uint8_t pga) //Setting PGA (input voltage range) -{ - _PGA = pga; - _ADCON = readRegister(ADCON_REG); //Read the most recent value of the register - - _ADCON = (_ADCON & 0b11111000) | (_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga - - writeRegister(ADCON_REG, _ADCON); - delay(200); - - updateConversionParameter(); //Update the multiplier according top the new PGA value +void ADS1256::setPGA(uint8_t pga) // Setting PGA (input voltage range) +{ + _PGA = pga; + _ADCON = readRegister(ADCON_REG); // Read the most recent value of the register + + _ADCON = (_ADCON & 0b11111000) | (_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga + + writeRegister(ADCON_REG, _ADCON); + delay(200); + + updateConversionParameter(); // Update the multiplier according top the new PGA value } -uint8_t ADS1256::getPGA() //Reading PGA from the ADCON register +uint8_t ADS1256::getPGA() // Reading PGA from the ADCON register { - uint8_t pgaValue = readRegister(ADCON_REG) & 0b00000111; - //Reading the ADCON_REG and keeping the first three bits. - - return(pgaValue); + uint8_t pgaValue = readRegister(ADCON_REG) & 0b00000111; + // Reading the ADCON_REG and keeping the first three bits. + + return (pgaValue); } -void ADS1256::setCLKOUT(uint8_t clkout) //Setting CLKOUT -{ - _ADCON = readRegister(ADCON_REG); //Read the most recent value of the register - - //Values: 0, 1, 2, 3 - - if(clkout == 0) - { - //00 - bitWrite(_ADCON, 6, 0); - bitWrite(_ADCON, 5, 0); - } - else if(clkout == 1) - { - //01 (default) - bitWrite(_ADCON, 6, 0); - bitWrite(_ADCON, 5, 1); - } - else if(clkout == 2) - { - //10 - bitWrite(_ADCON, 6, 1); - bitWrite(_ADCON, 5, 0); - } - else if(clkout == 3) - { - //11 - bitWrite(_ADCON, 6, 1); - bitWrite(_ADCON, 5, 1); - } - else{} - - writeRegister(ADCON_REG, _ADCON); - delay(100); +void ADS1256::setCLKOUT(uint8_t clkout) // Setting CLKOUT +{ + _ADCON = readRegister(ADCON_REG); // Read the most recent value of the register + + // Values: 0, 1, 2, 3 + + if (clkout == 0) + { + // 00 + bitWrite(_ADCON, 6, 0); + bitWrite(_ADCON, 5, 0); + } + else if (clkout == 1) + { + // 01 (default) + bitWrite(_ADCON, 6, 0); + bitWrite(_ADCON, 5, 1); + } + else if (clkout == 2) + { + // 10 + bitWrite(_ADCON, 6, 1); + bitWrite(_ADCON, 5, 0); + } + else if (clkout == 3) + { + // 11 + bitWrite(_ADCON, 6, 1); + bitWrite(_ADCON, 5, 1); + } + else + { + } + + writeRegister(ADCON_REG, _ADCON); + delay(100); } -void ADS1256::setSDCS(uint8_t sdcs) //Setting SDCS -{ - _ADCON = readRegister(ADCON_REG); //Read the most recent value of the register - - //Values: 0, 1, 2, 3 - - if(sdcs == 0) - { - //00 (default) - bitWrite(_ADCON, 4, 0); - bitWrite(_ADCON, 3, 0); - } - else if(sdcs == 1) - { - //01 - bitWrite(_ADCON, 4, 0); - bitWrite(_ADCON, 3, 1); - } - else if(sdcs == 2) - { - //10 - bitWrite(_ADCON, 4, 1); - bitWrite(_ADCON, 3, 0); - } - else if(sdcs == 3) - { - //11 - bitWrite(_ADCON, 4, 1); - bitWrite(_ADCON, 3, 1); - } - else{} - - writeRegister(ADCON_REG, _ADCON); - delay(100); +void ADS1256::setSDCS(uint8_t sdcs) // Setting SDCS +{ + _ADCON = readRegister(ADCON_REG); // Read the most recent value of the register + + // Values: 0, 1, 2, 3 + + if (sdcs == 0) + { + // 00 (default) + bitWrite(_ADCON, 4, 0); + bitWrite(_ADCON, 3, 0); + } + else if (sdcs == 1) + { + // 01 + bitWrite(_ADCON, 4, 0); + bitWrite(_ADCON, 3, 1); + } + else if (sdcs == 2) + { + // 10 + bitWrite(_ADCON, 4, 1); + bitWrite(_ADCON, 3, 0); + } + else if (sdcs == 3) + { + // 11 + bitWrite(_ADCON, 4, 1); + bitWrite(_ADCON, 3, 1); + } + else + { + } + + writeRegister(ADCON_REG, _ADCON); + delay(100); } -void ADS1256::setByteOrder(uint8_t byteOrder) //Setting byte order (MSB/LSB) -{ - _STATUS = readRegister(STATUS_REG); //Read the most recent value of the register - - if(byteOrder == 0) - { - //Byte order is MSB (default) - bitWrite(_STATUS, 3, 0); - //Set value of _STATUS at the third bit to 0 - } - else if(byteOrder == 1) - { - //Byte order is LSB - bitWrite(_STATUS, 3, 1); - //Set value of _STATUS at the third bit to 1 - } - else{} - - writeRegister(STATUS_REG, _STATUS); - delay(100); +void ADS1256::setByteOrder(uint8_t byteOrder) // Setting byte order (MSB/LSB) +{ + _STATUS = readRegister(STATUS_REG); // Read the most recent value of the register + + if (byteOrder == 0) + { + // Byte order is MSB (default) + bitWrite(_STATUS, 3, 0); + // Set value of _STATUS at the third bit to 0 + } + else if (byteOrder == 1) + { + // Byte order is LSB + bitWrite(_STATUS, 3, 1); + // Set value of _STATUS at the third bit to 1 + } + else + { + } + + writeRegister(STATUS_REG, _STATUS); + delay(100); } -uint8_t ADS1256::getByteOrder() //Getting byte order (MSB/LSB) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - - return bitRead(statusValue, 3); +uint8_t ADS1256::getByteOrder() // Getting byte order (MSB/LSB) +{ + uint8_t statusValue = readRegister(STATUS_REG); // Read the whole STATUS register + + return bitRead(statusValue, 3); } -void ADS1256::setAutoCal(uint8_t acal) //Setting ACAL (Automatic SYSCAL) -{ - _STATUS = readRegister(STATUS_REG); //Read the most recent value of the register - - if(acal == 0) - { - //Auto-calibration is disabled (default) - bitWrite(_STATUS, 2, 0); - //_STATUS |= B00000000; - } - else if(acal == 1) - { - //Auto-calibration is enabled - bitWrite(_STATUS, 2, 1); - //_STATUS |= B00000100; - } - else{} - - writeRegister(STATUS_REG, _STATUS); - delay(100); +void ADS1256::setAutoCal(uint8_t acal) // Setting ACAL (Automatic SYSCAL) +{ + _STATUS = readRegister(STATUS_REG); // Read the most recent value of the register + + if (acal == 0) + { + // Auto-calibration is disabled (default) + bitWrite(_STATUS, 2, 0); + //_STATUS |= B00000000; + } + else if (acal == 1) + { + // Auto-calibration is enabled + bitWrite(_STATUS, 2, 1); + //_STATUS |= B00000100; + } + else + { + } + + writeRegister(STATUS_REG, _STATUS); + delay(100); } -uint8_t ADS1256::getAutoCal() //Getting ACAL (Automatic SYSCAL) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - - return bitRead(statusValue, 2); +uint8_t ADS1256::getAutoCal() // Getting ACAL (Automatic SYSCAL) +{ + uint8_t statusValue = readRegister(STATUS_REG); // Read the whole STATUS register + + return bitRead(statusValue, 2); } -void ADS1256::setBuffer(uint8_t bufen) //Setting input buffer (Input impedance) -{ - _STATUS = readRegister(STATUS_REG); //Read the most recent value of the register - - if(bufen == 0) - { - //Analog input buffer is disabled (default) - //_STATUS |= B00000000; - bitWrite(_STATUS, 1, 0); - } - else if(bufen == 1) - { - //Analog input buffer is enabled (recommended) - //_STATUS |= B00000010; - bitWrite(_STATUS, 1, 1); - } - else{} - - writeRegister(STATUS_REG, _STATUS); - delay(100); +void ADS1256::setBuffer(uint8_t bufen) // Setting input buffer (Input impedance) +{ + _STATUS = readRegister(STATUS_REG); // Read the most recent value of the register + + if (bufen == 0) + { + // Analog input buffer is disabled (default) + //_STATUS |= B00000000; + bitWrite(_STATUS, 1, 0); + } + else if (bufen == 1) + { + // Analog input buffer is enabled (recommended) + //_STATUS |= B00000010; + bitWrite(_STATUS, 1, 1); + } + else + { + } + + writeRegister(STATUS_REG, _STATUS); + delay(100); } -uint8_t ADS1256::getBuffer() //Getting input buffer (Input impedance) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - - return bitRead(statusValue, 1); +uint8_t ADS1256::getBuffer() // Getting input buffer (Input impedance) +{ + uint8_t statusValue = readRegister(STATUS_REG); // Read the whole STATUS register + + return bitRead(statusValue, 1); } -void ADS1256::setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3) //Setting GPIO -{ - _GPIO = readRegister(IO_REG); //Read the most recent value of the register - - //Default: 11100000 - DEC: 224 - Ref: p32 I/O section - //Sets D3-D0 as input or output - uint8_t GPIO_bit7, GPIO_bit6, GPIO_bit5, GPIO_bit4; - - //Bit7: DIR3 - if(dir3 == 1) - { - GPIO_bit7 = 1; //D3 is input (default) - } - else - { - GPIO_bit7 = 0; //D3 is output - } - bitWrite(_GPIO, 7, GPIO_bit7); - //----------------------------------------------------- - //Bit6: DIR2 - if(dir2 == 1) - { - GPIO_bit6 = 1; //D2 is input (default) - } - else - { - GPIO_bit6 = 0; //D2 is output - } - bitWrite(_GPIO, 6, GPIO_bit6); - //----------------------------------------------------- - //Bit5: DIR1 - if(dir1 == 1) - { - GPIO_bit5 = 1; //D1 is input (default) - } - else - { - GPIO_bit5 = 0; //D1 is output - } - bitWrite(_GPIO, 5, GPIO_bit5); - //----------------------------------------------------- - //Bit4: DIR0 - if(dir0 == 1) - { - GPIO_bit4 = 1; //D0 is input - } - else - { - GPIO_bit4 = 0; //D0 is output (default) - } - bitWrite(_GPIO, 4, GPIO_bit4); - //----------------------------------------------------- - - writeRegister(IO_REG, _GPIO); - delay(100); +void ADS1256::setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3) // Setting GPIO +{ + _GPIO = readRegister(IO_REG); // Read the most recent value of the register + + // Default: 11100000 - DEC: 224 - Ref: p32 I/O section + // Sets D3-D0 as input or output + uint8_t GPIO_bit7, GPIO_bit6, GPIO_bit5, GPIO_bit4; + + // Bit7: DIR3 + if (dir3 == 1) + { + GPIO_bit7 = 1; // D3 is input (default) + } + else + { + GPIO_bit7 = 0; // D3 is output + } + bitWrite(_GPIO, 7, GPIO_bit7); + //----------------------------------------------------- + // Bit6: DIR2 + if (dir2 == 1) + { + GPIO_bit6 = 1; // D2 is input (default) + } + else + { + GPIO_bit6 = 0; // D2 is output + } + bitWrite(_GPIO, 6, GPIO_bit6); + //----------------------------------------------------- + // Bit5: DIR1 + if (dir1 == 1) + { + GPIO_bit5 = 1; // D1 is input (default) + } + else + { + GPIO_bit5 = 0; // D1 is output + } + bitWrite(_GPIO, 5, GPIO_bit5); + //----------------------------------------------------- + // Bit4: DIR0 + if (dir0 == 1) + { + GPIO_bit4 = 1; // D0 is input + } + else + { + GPIO_bit4 = 0; // D0 is output (default) + } + bitWrite(_GPIO, 4, GPIO_bit4); + //----------------------------------------------------- + + writeRegister(IO_REG, _GPIO); + delay(100); } -void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value) //Writing GPIO -{ - _GPIO = readRegister(IO_REG); - - //Sets D3-D0 output values - //It is important that first one must use setGPIO, then writeGPIO - - uint8_t GPIO_bit3, GPIO_bit2, GPIO_bit1, GPIO_bit0; - - //Bit3: DIR3 - if(dir3value == 1) - { - GPIO_bit3 = 1; - } - else - { - GPIO_bit3 = 0; - } - bitWrite(_GPIO, 3, GPIO_bit3); - //----------------------------------------------------- - //Bit2: DIR2 - if(dir2value == 1) - { - GPIO_bit2 = 1; - } - else - { - GPIO_bit2 = 0; - } - bitWrite(_GPIO, 2, GPIO_bit2); - //----------------------------------------------------- - //Bit1: DIR1 - if(dir1value == 1) - { - GPIO_bit1 = 1; - } - else - { - GPIO_bit1 = 0; - } - bitWrite(_GPIO, 1, GPIO_bit1); - //----------------------------------------------------- - //Bit0: DIR0 - if(dir0value == 1) - { - GPIO_bit0 = 1; - } - else - { - GPIO_bit0 = 0; - } - bitWrite(_GPIO, 0, GPIO_bit0); - //----------------------------------------------------- - - writeRegister(IO_REG, _GPIO); - delay(100); +void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value) // Writing GPIO +{ + _GPIO = readRegister(IO_REG); + + // Sets D3-D0 output values + // It is important that first one must use setGPIO, then writeGPIO + + uint8_t GPIO_bit3, GPIO_bit2, GPIO_bit1, GPIO_bit0; + + // Bit3: DIR3 + if (dir3value == 1) + { + GPIO_bit3 = 1; + } + else + { + GPIO_bit3 = 0; + } + bitWrite(_GPIO, 3, GPIO_bit3); + //----------------------------------------------------- + // Bit2: DIR2 + if (dir2value == 1) + { + GPIO_bit2 = 1; + } + else + { + GPIO_bit2 = 0; + } + bitWrite(_GPIO, 2, GPIO_bit2); + //----------------------------------------------------- + // Bit1: DIR1 + if (dir1value == 1) + { + GPIO_bit1 = 1; + } + else + { + GPIO_bit1 = 0; + } + bitWrite(_GPIO, 1, GPIO_bit1); + //----------------------------------------------------- + // Bit0: DIR0 + if (dir0value == 1) + { + GPIO_bit0 = 1; + } + else + { + GPIO_bit0 = 0; + } + bitWrite(_GPIO, 0, GPIO_bit0); + //----------------------------------------------------- + + writeRegister(IO_REG, _GPIO); + delay(100); } -uint8_t ADS1256::readGPIO(uint8_t gpioPin) //Reading GPIO -{ - uint8_t GPIO_bit3, GPIO_bit2, GPIO_bit1, GPIO_bit0, GPIO_return; - - _GPIO = readRegister(IO_REG); //Read the GPIO register - - //Save each bit values in a variable - GPIO_bit3 = bitRead(_GPIO, 3); - GPIO_bit2 = bitRead(_GPIO, 2); - GPIO_bit1 = bitRead(_GPIO, 1); - GPIO_bit0 = bitRead(_GPIO, 0); - - delay(100); - - switch(gpioPin) //Selecting which value should be returned - { - case 0: - GPIO_return = GPIO_bit0; - break; - - case 1: - GPIO_return = GPIO_bit1; - break; - - case 2: - GPIO_return = GPIO_bit2; - break; - - case 3: - GPIO_return = GPIO_bit3; - break; - } - - return GPIO_return; - +uint8_t ADS1256::readGPIO(uint8_t gpioPin) // Reading GPIO +{ + uint8_t GPIO_bit3, GPIO_bit2, GPIO_bit1, GPIO_bit0, GPIO_return; + + _GPIO = readRegister(IO_REG); // Read the GPIO register + + // Save each bit values in a variable + GPIO_bit3 = bitRead(_GPIO, 3); + GPIO_bit2 = bitRead(_GPIO, 2); + GPIO_bit1 = bitRead(_GPIO, 1); + GPIO_bit0 = bitRead(_GPIO, 0); + + delay(100); + + switch (gpioPin) // Selecting which value should be returned + { + case 0: + GPIO_return = GPIO_bit0; + break; + + case 1: + GPIO_return = GPIO_bit1; + break; + + case 2: + GPIO_return = GPIO_bit2; + break; + + case 3: + GPIO_return = GPIO_bit3; + break; + } + + return GPIO_return; } void ADS1256::sendDirectCommand(uint8_t directCommand) { - //Direct commands can be found in the datasheet Page 34, Table 24. - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + // Direct commands can be found in the datasheet Page 34, Table 24. + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" - delayMicroseconds(5); - _spi->transfer(directCommand); //Send Command - delayMicroseconds(5); - CS_HIGH(); //REF: P34: "CS must stay low during the entire command sequence" + CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" + delayMicroseconds(5); + _spi->transfer(directCommand); // Send Command + delayMicroseconds(5); + CS_HIGH(); // REF: P34: "CS must stay low during the entire command sequence" - _spi->endTransaction(); + _spi->endTransaction(); } - -float ADS1256::convertToVoltage(int32_t rawData) //Converting the 24-bit data into a voltage value -{ - return(conversionParameter * rawData); +float ADS1256::convertToVoltage(int32_t rawData) // Converting the 24-bit data into a voltage value +{ + return (conversionParameter * rawData); } void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite) -{ - waitForLowDRDY(); +{ + waitForLowDRDY(); - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + // SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] + CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24] - delayMicroseconds(5); //see t6 in the datasheet + delayMicroseconds(5); // see t6 in the datasheet - _spi->transfer(0x50 | registerAddress); // 0x50 = 01010000 = WREG + _spi->transfer(0x50 | registerAddress); // 0x50 = 01010000 = WREG - _spi->transfer(0x00); //2nd (empty) command byte + _spi->transfer(0x00); // 2nd (empty) command byte - _spi->transfer(registerValueToWrite); //pass the value to the register - - CS_HIGH(); - _spi->endTransaction(); - delay(100); - + _spi->transfer(registerValueToWrite); // pass the value to the register + + CS_HIGH(); + _spi->endTransaction(); + delay(100); } -long ADS1256::readRegister(uint8_t registerAddress) //Reading a register +long ADS1256::readRegister(uint8_t registerAddress) // Reading a register { - waitForLowDRDY(); - - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. + waitForLowDRDY(); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + // SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. - _spi->transfer(0x10 | registerAddress); //0x10 = 0001000 = RREG - OR together the two numbers (command + address) + CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x00); //2nd (empty) command byte + _spi->transfer(0x10 | registerAddress); // 0x10 = 0001000 = RREG - OR together the two numbers (command + address) - delayMicroseconds(5); //see t6 in the datasheet + _spi->transfer(0x00); // 2nd (empty) command byte - uint8_t regValue = _spi->transfer(0xFF); //read out the register value + delayMicroseconds(5); // see t6 in the datasheet - CS_HIGH(); - _spi->endTransaction(); - delay(100); - return regValue; -} + uint8_t regValue = _spi->transfer(0xFF); // read out the register value + CS_HIGH(); + _spi->endTransaction(); + delay(100); + return regValue; +} -long ADS1256::readSingle() //Reading a single value ONCE using the RDATA command +long ADS1256::readSingle() // Reading a single value ONCE using the RDATA command { - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" - waitForLowDRDY(); - _spi->transfer(0b00000001); //Issue RDATA (0000 0001) command - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" + waitForLowDRDY(); + _spi->transfer(0b00000001); // Issue RDATA (0000 0001) command + delayMicroseconds(7); // Wait t6 time (~6.51 us) REF: P34, FIG:30. + + _outputBuffer[0] = _spi->transfer(0); // MSB + _outputBuffer[1] = _spi->transfer(0); // Mid-byte + _outputBuffer[2] = _spi->transfer(0); // LSB + + // Shifting and combining the above three items into a single, 24-bit number + _outputValue = ((long)_outputBuffer[0] << 16) | ((long)_outputBuffer[1] << 8) | (_outputBuffer[2]); + _outputValue = convertSigned24BitToLong(_outputValue); - _outputBuffer[0] = _spi->transfer(0); // MSB - _outputBuffer[1] = _spi->transfer(0); // Mid-byte - _outputBuffer[2] = _spi->transfer(0); // LSB + CS_HIGH(); // We finished the command sequence, so we set CS to HIGH + _spi->endTransaction(); - //Shifting and combining the above three items into a single, 24-bit number - _outputValue = ((long)_outputBuffer[0]<<16) | ((long)_outputBuffer[1]<<8) | (_outputBuffer[2]); - _outputValue = convertSigned24BitToLong(_outputValue); - - CS_HIGH(); //We finished the command sequence, so we set CS to HIGH - _spi->endTransaction(); - - return(_outputValue); + return (_outputValue); } -long ADS1256::readSingleContinuous() //Reads the recently selected input channel using RDATAC -{ - if(_isAcquisitionRunning == false) - { - _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" - waitForLowDRDY(); - _spi->transfer(0b00000011); //Issue RDATAC (0000 0011) - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. - } - else - { - waitForLowDRDY(); - } - - _outputBuffer[0] = _spi->transfer(0); // MSB - _outputBuffer[1] = _spi->transfer(0); // Mid-byte - _outputBuffer[2] = _spi->transfer(0); // LSB - - _outputValue = ((long)_outputBuffer[0]<<16) | ((long)_outputBuffer[1]<<8) | (_outputBuffer[2]); - _outputValue = convertSigned24BitToLong(_outputValue); - - waitForHighDRDY(); - - return _outputValue; +long ADS1256::readSingleContinuous() // Reads the recently selected input channel using RDATAC +{ + if (_isAcquisitionRunning == false) + { + _isAcquisitionRunning = true; + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" + waitForLowDRDY(); + _spi->transfer(0b00000011); // Issue RDATAC (0000 0011) + delayMicroseconds(7); // Wait t6 time (~6.51 us) REF: P34, FIG:30. + } + else + { + waitForLowDRDY(); + } + + _outputBuffer[0] = _spi->transfer(0); // MSB + _outputBuffer[1] = _spi->transfer(0); // Mid-byte + _outputBuffer[2] = _spi->transfer(0); // LSB + + _outputValue = ((long)_outputBuffer[0] << 16) | ((long)_outputBuffer[1] << 8) | (_outputBuffer[2]); + _outputValue = convertSigned24BitToLong(_outputValue); + + waitForHighDRDY(); + + return _outputValue; } -long ADS1256::cycleSingle() -{ - if(_isAcquisitionRunning == false) - { - _isAcquisitionRunning = true; - _cycle = 0; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX - _spi->transfer(0x00); - _spi->transfer(SING_0); //AIN0+AINCOM - CS_HIGH(); - delay(50); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - } - else - {} - - if(_cycle < 8) - { - _outputValue = 0; - waitForLowDRDY(); - //Step 1. - Updating MUX - switch (_cycle) - { - //Channels are written manually - case 0: //Channel 2 - updateMUX(SING_1); //AIN1+AINCOM - break; - - case 1: //Channel 3 - updateMUX(SING_2); //AIN2+AINCOM - break; - - case 2: //Channel 4 - updateMUX(SING_3); //AIN3+AINCOM - break; - - case 3: //Channel 5 - updateMUX(SING_4); //AIN4+AINCOM - break; - - case 4: //Channel 6 - updateMUX(SING_5); //AIN5+AINCOM - break; - - case 5: //Channel 7 - updateMUX(SING_6); //AIN6+AINCOM - break; - - case 6: //Channel 8 - updateMUX(SING_7); //AIN7+AINCOM - break; - - case 7: //Channel 1 - updateMUX(SING_0); //AIN0+AINCOM - break; - } - //Step 2. - _spi->transfer(0b11111100); //SYNC - delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(0b11111111); //WAKEUP - - //Step 3. - //Issue RDATA (0000 0001) command - _spi->transfer(0b00000001); - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. - - _outputBuffer[0] = _spi->transfer(0x0F); // MSB - _outputBuffer[1] = _spi->transfer(0x0F); // Mid-byte - _outputBuffer[2] = _spi->transfer(0x0F); // LSB - - _outputValue = ((long)_outputBuffer[0]<<16) | ((long)_outputBuffer[1]<<8) | (_outputBuffer[2]); - _outputValue = convertSigned24BitToLong(_outputValue); - - _cycle++; //Increase cycle - This will move to the next MUX input channel - if(_cycle == 8) - { - _cycle = 0; //Reset to 0 - Restart conversion from the 1st input channel - } - } - - return _outputValue; +/** + * @brief Cycle through a list of single-ended input channels (SING_x constants). + * @param muxList Pointer to array of SING_x constants (e.g. SING_0, SING_7, ...). + * @param muxCount Number of entries in muxList. If 0, defaults to all single-ended channels. + * If muxList is nullptr, defaults to all single-ended channels (SING_0 to SING_7). + * This function cycles through the provided list of single-ended channels, + * updating the MUX register for each channel and acquiring a value. + * It can be used for continuous acquisition of multiple channels in a single call. + * The function will store the provided muxList and reuse it in subsequent calls + * until a new list is provided or the acquisition is stopped.* + * @return Last acquired value. + */ +long ADS1256::cycleSingle(const uint8_t *muxList, size_t muxCount) +{ + // Default to all single-ended channels if no list is provided + static const uint8_t defaultMuxList[8] = { + SING_0, SING_1, SING_2, SING_3, SING_4, SING_5, SING_6, SING_7}; + + // Static storage for the active mux list and count + static uint8_t storedMuxList[8]; + static size_t storedMuxCount = 0; + static size_t cycleIdx = 0; + + if (_isAcquisitionRunning == false) + { + // If no list provided, use default + if (muxList == nullptr || muxCount == 0) + { + muxList = defaultMuxList; + muxCount = 8; + } + // Store the mux list for subsequent calls + if (muxCount > 8) + muxCount = 8; // Prevent overflow + memcpy(storedMuxList, muxList, muxCount); + storedMuxCount = muxCount; + cycleIdx = 0; + + _isAcquisitionRunning = true; + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + digitalWrite(_CS_pin, LOW); // CS must stay LOW during the entire sequence [Ref: P34, T24] + _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX + _spi->transfer(0x00); + _spi->transfer(storedMuxList[cycleIdx]); // Set initial MUX + digitalWrite(_CS_pin, HIGH); + delay(50); + digitalWrite(_CS_pin, LOW); + } + else + { + // If running and no arguments, use stored list + if (muxList == nullptr || muxCount == 0) + { + muxList = storedMuxList; + muxCount = storedMuxCount; + } + // If running and arguments are given, ignore them (keep using stored list) + else + { + muxList = storedMuxList; + muxCount = storedMuxCount; + } + } + + _outputValue = 0; + waitForLowDRDY(); + + // Step 1. - Updating MUX to current channel + updateMUX(storedMuxList[cycleIdx]); + + // Step 2. + _spi->transfer(0b11111100); // SYNC + delayMicroseconds(4); // t11 delay + _spi->transfer(0b11111111); // WAKEUP + + // Step 3. + _spi->transfer(0b00000001); // Issue RDATA (0000 0001) command + delayMicroseconds(7); // Wait t6 time + + _outputBuffer[0] = _spi->transfer(0x0F); // MSB + _outputBuffer[1] = _spi->transfer(0x0F); // Mid-byte + _outputBuffer[2] = _spi->transfer(0x0F); // LSB + + _outputValue = ((long)_outputBuffer[0] << 16) | ((long)_outputBuffer[1] << 8) | (_outputBuffer[2]); + _outputValue = convertSigned24BitToLong(_outputValue); + + // Advance to next channel in the list + cycleIdx++; + if (cycleIdx >= storedMuxCount) + { + cycleIdx = 0; + } + + return _outputValue; } -long ADS1256::cycleDifferential() -{ - if(_isAcquisitionRunning == false) - { - _cycle = 0; - _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); - - //Set the AIN0+AIN1 as inputs manually - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX - _spi->transfer(0x00); - _spi->transfer(DIFF_0_1); //AIN0+AIN1 - CS_HIGH(); - delay(50); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - } - else - {} - - if(_cycle < 4) - { - _outputValue = 0; - //DRDY has to go low - waitForLowDRDY(); - - //Step 1. - Updating MUX - switch (_cycle) - { - case 0: //Channel 2 - updateMUX(DIFF_2_3); //AIN2+AIN3 - break; - - case 1: //Channel 3 - updateMUX(DIFF_4_5); //AIN4+AIN5 - break; - - case 2: //Channel 4 - updateMUX(DIFF_6_7); //AIN6+AIN7 - break; - - case 3: //Channel 1 - updateMUX(DIFF_0_1); //AIN0+AIN1 - break; - } - - _spi->transfer(0b11111100); //SYNC - delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(0b11111111); //WAKEUP - - //Step 3. - _spi->transfer(0b00000001); //Issue RDATA (0000 0001) command - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. - - _outputBuffer[0] = _spi->transfer(0); // MSB - _outputBuffer[1] = _spi->transfer(0); // Mid-byte - _outputBuffer[2] = _spi->transfer(0); // LSB - - _outputValue = ((long)_outputBuffer[0]<<16) | ((long)_outputBuffer[1]<<8) | (_outputBuffer[2]); - _outputValue = convertSigned24BitToLong(_outputValue); - - _cycle++; - if(_cycle == 4) - { - _cycle = 0; - //After the 4th cycle, we reset to zero so the next iteration reads the 1st MUX again - } - } - - return _outputValue; +long ADS1256::cycleDifferential(int8_t stepwidth /* = 1 */) // Cycling through the differential inputs (AINx + AINy) with a channel step width of stepwidth (e.g. stepwidth = 2 means AIN0+AIN1, AIN4+AIN5, AIN0+AIN1, AIN4+AIN5, etc.) +{ + if (_isAcquisitionRunning == false) + { + _cycle = 0; + _isAcquisitionRunning = true; + _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + + // Set the AIN0+AIN1 as inputs manually + digitalWrite(_CS_pin, LOW); // CS must stay LOW during the entire sequence [Ref: P34, T24] + _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX + _spi->transfer(0x00); + _spi->transfer(DIFF_0_1); // AIN0+AIN1 + digitalWrite(_CS_pin, HIGH); + delay(50); + digitalWrite(_CS_pin, LOW); // CS must stay LOW during the entire sequence [Ref: P34, T24] + } + else + { + } + + if (_cycle < 4) + { + _outputValue = 0; + // DRDY has to go low + waitForLowDRDY(); + + // Step 1. - Updating MUX + switch (_cycle) + { + case 0: // Channel 2 + updateMUX(DIFF_2_3); // AIN2+AIN3 + break; + + case 1: // Channel 3 + updateMUX(DIFF_4_5); // AIN4+AIN5 + break; + + case 2: // Channel 4 + updateMUX(DIFF_6_7); // AIN6+AIN7 + break; + + case 3: // Channel 1 + updateMUX(DIFF_0_1); // AIN0+AIN1 + break; + } + + _spi->transfer(0b11111100); // SYNC + delayMicroseconds(4); // t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us + _spi->transfer(0b11111111); // WAKEUP + + // Step 3. + _spi->transfer(0b00000001); // Issue RDATA (0000 0001) command + delayMicroseconds(7); // Wait t6 time (~6.51 us) REF: P34, FIG:30. + + _outputBuffer[0] = _spi->transfer(0); // MSB + _outputBuffer[1] = _spi->transfer(0); // Mid-byte + _outputBuffer[2] = _spi->transfer(0); // LSB + + _outputValue = ((long)_outputBuffer[0] << 16) | ((long)_outputBuffer[1] << 8) | (_outputBuffer[2]); + _outputValue = convertSigned24BitToLong(_outputValue); + + _cycle += stepwidth; // Increase cycle - This will move to the next MUX input channel + if (_cycle >= 4) + { + _cycle = 0; + // After the 4th cycle, we reset to zero so the next iteration reads the 1st MUX again + } + } + + return _outputValue; } void ADS1256::updateConversionParameter() { - conversionParameter = ((2.0 * _VREF) / 8388608.0) / (pow(2, _PGA)); //Calculate the "bit to Volts" multiplier - //8388608 = 2^{23} - 1, REF: p23, Table 16. + conversionParameter = ((2.0 * _VREF) / 8388608.0) / (pow(2, _PGA)); // Calculate the "bit to Volts" multiplier + // 8388608 = 2^{23} - 1, REF: p23, Table 16. } void ADS1256::updateMUX(uint8_t muxValue) { - _spi->transfer(0x50 | MUX_REG); //Write to the MUX register (0x50 is the WREG command) - _spi->transfer(0x00); - _spi->transfer(muxValue); //Write the new MUX value + _spi->transfer(0x50 | MUX_REG); // Write to the MUX register (0x50 is the WREG command) + _spi->transfer(0x00); + _spi->transfer(muxValue); // Write the new MUX value } inline void ADS1256::CS_LOW() { - if (_CS_pin != PIN_UNUSED) //Sets CS LOW if it is not an unused pin - { + if (_CS_pin != PIN_UNUSED) // Sets CS LOW if it is not an unused pin + { digitalWrite(_CS_pin, LOW); - } + } } inline void ADS1256::CS_HIGH() { - if (_CS_pin != PIN_UNUSED) //Sets CS HIGH if it is not an unused pin - { + if (_CS_pin != PIN_UNUSED) // Sets CS HIGH if it is not an unused pin + { digitalWrite(_CS_pin, HIGH); - } + } } \ No newline at end of file diff --git a/src/ADS1256.h b/src/ADS1256.h index 1ded2e2..94a0e1f 100644 --- a/src/ADS1256.h +++ b/src/ADS1256.h @@ -1,11 +1,11 @@ -//ADS1256 header file +// ADS1256 header file /* Name: ADS1256.h Created: 2022/07/14 Author: Curious Scientist Editor: Notepad++ Comment: Visit https://curiousscientist.tech/blog/ADS1256-custom-library - Special thanks to + Special thanks to Abraão Queiroz for spending time on the code and suggesting corrections for ESP32 microcontrollers Benjamin Pelletier for pointing out and fixing an issue around the handling of the DRDY signal */ @@ -15,50 +15,50 @@ #include -//Differential inputs -#define DIFF_0_1 0b00000001 //A0 + A1 as differential input -#define DIFF_2_3 0b00100011 //A2 + A3 as differential input -#define DIFF_4_5 0b01000101 //A4 + A5 as differential input -#define DIFF_6_7 0b01100111 //A6 + A7 as differential input - -//Single-ended inputs -#define SING_0 0b00001111 //A0 + GND (common) as single-ended input -#define SING_1 0b00011111 //A1 + GND (common) as single-ended input -#define SING_2 0b00101111 //A2 + GND (common) as single-ended input -#define SING_3 0b00111111 //A3 + GND (common) as single-ended input -#define SING_4 0b01001111 //A4 + GND (common) as single-ended input -#define SING_5 0b01011111 //A5 + GND (common) as single-ended input -#define SING_6 0b01101111 //A6 + GND (common) as single-ended input -#define SING_7 0b01111111 //A7 + GND (common) as single-ended input - -//PGA settings //Input voltage range -#define PGA_1 0b00000000 //± 5 V -#define PGA_2 0b00000001 //± 2.5 V -#define PGA_4 0b00000010 //± 1.25 V -#define PGA_8 0b00000011 //± 625 mV -#define PGA_16 0b00000100 //± 312.5 mV +// Differential inputs +#define DIFF_0_1 0b00000001 // A0 + A1 as differential input +#define DIFF_2_3 0b00100011 // A2 + A3 as differential input +#define DIFF_4_5 0b01000101 // A4 + A5 as differential input +#define DIFF_6_7 0b01100111 // A6 + A7 as differential input + +// Single-ended inputs +#define SING_0 0b00001111 // A0 + GND (common) as single-ended input +#define SING_1 0b00011111 // A1 + GND (common) as single-ended input +#define SING_2 0b00101111 // A2 + GND (common) as single-ended input +#define SING_3 0b00111111 // A3 + GND (common) as single-ended input +#define SING_4 0b01001111 // A4 + GND (common) as single-ended input +#define SING_5 0b01011111 // A5 + GND (common) as single-ended input +#define SING_6 0b01101111 // A6 + GND (common) as single-ended input +#define SING_7 0b01111111 // A7 + GND (common) as single-ended input + +// PGA settings //Input voltage range +#define PGA_1 0b00000000 // ± 5 V +#define PGA_2 0b00000001 // ± 2.5 V +#define PGA_4 0b00000010 // ± 1.25 V +#define PGA_8 0b00000011 // ± 625 mV +#define PGA_16 0b00000100 // ± 312.5 mV #define PGA_32 0b00000101 //+ 156.25 mV -#define PGA_64 0b00000110 //± 78.125 mV - -//Datarate //DEC -#define DRATE_30000SPS 0b11110000 //240 -#define DRATE_15000SPS 0b11100000 //224 -#define DRATE_7500SPS 0b11010000 //208 -#define DRATE_3750SPS 0b11000000 //192 -#define DRATE_2000SPS 0b10110000 //176 -#define DRATE_1000SPS 0b10100001 //161 -#define DRATE_500SPS 0b10010010 //146 -#define DRATE_100SPS 0b10000010 //130 -#define DRATE_60SPS 0b01110010 //114 -#define DRATE_50SPS 0b01100011 //99 -#define DRATE_30SPS 0b01010011 //83 -#define DRATE_25SPS 0b01000011 //67 -#define DRATE_15SPS 0b00110011 //51 -#define DRATE_10SPS 0b00100011 //35 -#define DRATE_5SPS 0b00010011 //19 -#define DRATE_2SPS 0b00000011 //3 - -//Status register +#define PGA_64 0b00000110 // ± 78.125 mV + +// Datarate //DEC +#define DRATE_30000SPS 0b11110000 // 240 +#define DRATE_15000SPS 0b11100000 // 224 +#define DRATE_7500SPS 0b11010000 // 208 +#define DRATE_3750SPS 0b11000000 // 192 +#define DRATE_2000SPS 0b10110000 // 176 +#define DRATE_1000SPS 0b10100001 // 161 +#define DRATE_500SPS 0b10010010 // 146 +#define DRATE_100SPS 0b10000010 // 130 +#define DRATE_60SPS 0b01110010 // 114 +#define DRATE_50SPS 0b01100011 // 99 +#define DRATE_30SPS 0b01010011 // 83 +#define DRATE_25SPS 0b01000011 // 67 +#define DRATE_15SPS 0b00110011 // 51 +#define DRATE_10SPS 0b00100011 // 35 +#define DRATE_5SPS 0b00010011 // 19 +#define DRATE_2SPS 0b00000011 // 3 + +// Status register #define BITORDER_MSB 0 #define BITORDER_LSB 1 #define ACAL_DISABLED 0 @@ -66,7 +66,7 @@ #define BUFFER_DISABLED 0 #define BUFFER_ENABLED 1 -//Register addresses +// Register addresses #define STATUS_REG 0x00 #define MUX_REG 0x01 #define ADCON_REG 0x02 @@ -79,7 +79,7 @@ #define FSC1_REG 0x09 #define FSC2_REG 0x0A -//Command definitions +// Command definitions #define WAKEUP 0b00000000 #define RDATA 0b00000001 #define RDATAC 0b00000011 @@ -96,94 +96,91 @@ #define RESET 0b11111110 //---------------------------------------------------------------- - class ADS1256 -{ +{ public: -static constexpr int8_t PIN_UNUSED = -1; - - //Constructor - ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYNC_pin, const int8_t CS_pin, float VREF, SPIClass* spi = &SPI); - - //Initializing function - void InitializeADC(); - //ADS1256(int drate, int pga, int byteOrder, bool bufen); - - //Read a register - long readRegister(uint8_t registerAddress); - - //Write a register - void writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite); - - //Individual methods - void setDRATE(uint8_t drate); - void setPGA(uint8_t pga); - uint8_t getPGA(); - void setMUX(uint8_t mux); - void setByteOrder(uint8_t byteOrder); - uint8_t getByteOrder(); - void setBuffer(uint8_t bufen); - uint8_t getBuffer(); - void setAutoCal(uint8_t acal); - uint8_t getAutoCal(); - void setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3); - void writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value); - uint8_t readGPIO(uint8_t gpioPin); - void setCLKOUT(uint8_t clkout); - void setSDCS(uint8_t sdcs); - void sendDirectCommand(uint8_t directCommand); - - //Get a single conversion - long readSingle(); - - //Single input continuous reading - long readSingleContinuous(); - - //Cycling through the single-ended inputs - long cycleSingle(); //Ax + COM - - //Cycling through the differential inputs - long cycleDifferential(); //Ax + Ay - - //Converts the reading into a voltage value - float convertToVoltage(int32_t rawData); - - //Stop AD - void stopConversion(); - + static constexpr int8_t PIN_UNUSED = -1; + + // Constructor + ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYNC_pin, const int8_t CS_pin, float VREF, SPIClass *spi = &SPI); + + // Initializing function + void InitializeADC(); + // ADS1256(int drate, int pga, int byteOrder, bool bufen); + + // Read a register + long readRegister(uint8_t registerAddress); + + // Write a register + void writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite); + + // Individual methods + void setDRATE(uint8_t drate); + void setPGA(uint8_t pga); + uint8_t getPGA(); + void setMUX(uint8_t mux); + void setByteOrder(uint8_t byteOrder); + uint8_t getByteOrder(); + void setBuffer(uint8_t bufen); + uint8_t getBuffer(); + void setAutoCal(uint8_t acal); + uint8_t getAutoCal(); + void setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3); + void writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value); + uint8_t readGPIO(uint8_t gpioPin); + void setCLKOUT(uint8_t clkout); + void setSDCS(uint8_t sdcs); + void sendDirectCommand(uint8_t directCommand); + + // Get a single conversion + long readSingle(); + + // Single input continuous reading + long readSingleContinuous(); + + // Cycling through the single-ended inputs + long cycleSingle(const uint8_t *muxList, size_t muxCount); // Ax + COM, cycles in steps of stepwidth (e.g. stepwidth = 7 means AIN0, AIN7, AIN0, AIN7, etc.) + // Cycling through the differential inputs + long cycleDifferential(int8_t stepwidth = 1); // Ax + Ay, cycles in steps of stepwidth (e.g. stepwidth = 2 means AIN0 + AIN1, AIN4 + AIN5, AIN0 + AIN1, AIN4 + AIN5, etc.) + + // Converts the reading into a voltage value + float convertToVoltage(int32_t rawData); + + // Stop AD + void stopConversion(); + private: - -SPIClass* _spi; //Pointer to an SPIClass object - -void waitForLowDRDY(); // Block until DRDY is low -void waitForHighDRDY(); // Block until DRDY is high -void updateMUX(uint8_t muxValue); -inline void CS_LOW(); -inline void CS_HIGH(); - -void updateConversionParameter(); //Refresh the conversion parameter based on the PGA - -float _VREF = 0; //Value of the reference voltage -float conversionParameter = 0; //PGA-dependent multiplier -//Pins -int8_t _DRDY_pin; //Pin assigned for DRDY -int8_t _RESET_pin; //Pin assigned for RESET -int8_t _SYNC_pin; //Pin assigned for SYNC -int8_t _CS_pin; //Pin assigned for CS - -//Register values -byte _DRATE; //Value of the DRATE register -byte _ADCON; //Value of the ADCON register -byte _MUX; //Value of the MUX register -byte _PGA; //Value of the PGA (within ADCON) -byte _GPIO; //Value of the GPIO register -byte _STATUS; //Value of the status register -byte _GPIOvalue; //GPIO value -byte _ByteOrder; //Byte order - -byte _outputBuffer[3]; //3-byte (24-bit) buffer for the fast acquisition - Single-channel, continuous -long _outputValue; //Combined value of the _outputBuffer[3] -bool _isAcquisitionRunning; //bool that keeps track of the acquisition (running or not) -uint8_t _cycle; //Tracks the cycles as the MUX is cycling through the input channels + SPIClass *_spi; // Pointer to an SPIClass object + + void waitForLowDRDY(); // Block until DRDY is low + void waitForHighDRDY(); // Block until DRDY is high + void updateMUX(uint8_t muxValue); + inline void CS_LOW(); + inline void CS_HIGH(); + + void updateConversionParameter(); // Refresh the conversion parameter based on the PGA + + float _VREF = 0; // Value of the reference voltage + float conversionParameter = 0; // PGA-dependent multiplier + // Pins + int8_t _DRDY_pin; // Pin assigned for DRDY + int8_t _RESET_pin; // Pin assigned for RESET + int8_t _SYNC_pin; // Pin assigned for SYNC + int8_t _CS_pin; // Pin assigned for CS + + // Register values + byte _DRATE; // Value of the DRATE register + byte _ADCON; // Value of the ADCON register + byte _MUX; // Value of the MUX register + byte _PGA; // Value of the PGA (within ADCON) + byte _GPIO; // Value of the GPIO register + byte _STATUS; // Value of the status register + byte _GPIOvalue; // GPIO value + byte _ByteOrder; // Byte order + + byte _outputBuffer[3]; // 3-byte (24-bit) buffer for the fast acquisition - Single-channel, continuous + long _outputValue; // Combined value of the _outputBuffer[3] + bool _isAcquisitionRunning; // bool that keeps track of the acquisition (running or not) + uint8_t _cycle; // Tracks the cycles as the MUX is cycling through the input channels }; #endif \ No newline at end of file