diff --git a/RotaxMonitor/lib/ADS1256/ADS1256.cpp b/RotaxMonitor/lib/ADS1256/ADS1256.cpp index eef8eac..9467dd7 100644 --- a/RotaxMonitor/lib/ADS1256/ADS1256.cpp +++ b/RotaxMonitor/lib/ADS1256/ADS1256.cpp @@ -1,4 +1,4 @@ -//ADS1256 cpp file +// ADS1256 cpp file /* Name: ADS1256.cpp Created: 2022/07/14 @@ -17,389 +17,426 @@ #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) +void drdyCallback(void *arg) +{ + auto cls = (ADS1256 *)arg; + if (!arg) + return; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + if (digitalRead(cls->getDRDYpin())) // impose wait on low { - pinMode(_RESET_pin, OUTPUT); + xSemaphoreTakeFromISR(cls->getDRDYsemaphoreLow(), &xHigherPriorityTaskWoken); + xSemaphoreGiveFromISR(cls->getDRDYsemaphoreHigh(), &xHigherPriorityTaskWoken); } - - if(SYNC_pin != PIN_UNUSED) + else // impose wait on high { - pinMode(_SYNC_pin, OUTPUT); + xSemaphoreTakeFromISR(cls->getDRDYsemaphoreHigh(), &xHigherPriorityTaskWoken); + xSemaphoreGiveFromISR(cls->getDRDYsemaphoreLow(), &xHigherPriorityTaskWoken); } - - if(CS_pin != PIN_UNUSED) + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} + +// 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), + m_DRDY_pin(DRDY_pin), m_RESET_pin(RESET_pin), m_SYNC_pin(SYNC_pin), m_CS_pin(CS_pin), m_VREF(VREF), m_PGA(0) +{ + pinMode(m_DRDY_pin, INPUT); + + if (RESET_pin != PIN_UNUSED) { - pinMode(_CS_pin, OUTPUT); - } - + pinMode(m_RESET_pin, OUTPUT); + } + + if (SYNC_pin != PIN_UNUSED) + { + pinMode(m_SYNC_pin, OUTPUT); + } + + if (CS_pin != PIN_UNUSED) + { + pinMode(m_CS_pin, OUTPUT); + } + updateConversionParameter(); -} -//Initialization + m_drdyHigh = xSemaphoreCreateBinary(); + m_drdyLow = xSemaphoreCreateBinary(); + xSemaphoreGive(m_drdyHigh); + xSemaphoreGive(m_drdyLow); + attachInterruptArg(DRDY_pin, drdyCallback, (void *)this, CHANGE); +} + +// 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 (m_RESET_pin != PIN_UNUSED) + { + digitalWrite(m_RESET_pin, LOW); + delay(200); + digitalWrite(m_RESET_pin, HIGH); // RESET is set to high + delay(1000); + } + + // Sync pin is also treated if it is defined + if (m_SYNC_pin != PIN_UNUSED) + { + digitalWrite(m_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 = DIFF_0_1; //MUX AIN0+AIN1 - writeRegister(MUX_REG, _MUX); - delay(200); - - _ADCON = WAKEUP; //ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) - writeRegister(ADCON_REG, _ADCON); - delay(200); - - updateConversionParameter(); - - _DRATE = DRATE_100SPS; //100SPS - writeRegister(DRATE_REG, _DRATE); - delay(200); - - sendDirectCommand(SELFCAL); //Offset and self-gain calibration - delay(200); + // 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); - _isAcquisitionRunning = false; //MCU will be waiting to start a continuous acquisition + m_STATUS = 0b00110110; // BUFEN and ACAL enabled, Order is MSB, rest is read only + writeRegister(STATUS_REG, m_STATUS); + delay(200); + + m_MUX = DIFF_0_1; // MUX AIN0+AIN1 + writeRegister(MUX_REG, m_MUX); + delay(200); + + m_ADCON = WAKEUP; // ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) + writeRegister(ADCON_REG, m_ADCON); + delay(200); + + updateConversionParameter(); + + m_DRATE = DRATE_100SPS; // 100SPS + writeRegister(DRATE_REG, m_DRATE); + delay(200); + + sendDirectCommand(SELFCAL); // Offset and self-gain calibration + delay(200); + + m_isAcquisitionRunning = false; // MCU will be waiting to start a continuous acquisition } void ADS1256::waitForLowDRDY() -{ - while (digitalRead(_DRDY_pin) == HIGH) {} +{ + xSemaphoreTake(m_drdyLow, pdMS_TO_TICKS(10)); + xSemaphoreGive(m_drdyLow); } 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) {} -#endif +{ + xSemaphoreTake(m_drdyHigh, pdMS_TO_TICKS(10)); + xSemaphoreGive(m_drdyHigh); } -void ADS1256::stopConversion() //Sending SDATAC to stop the continuous conversion -{ - waitForLowDRDY(); //SDATAC should be called after DRDY goes LOW (p35. Figure 33) - _spi->transfer(SDATAC); //Send SDATAC to the ADC - CS_HIGH(); //We finished the command sequence, so we switch it back to HIGH +void ADS1256::stopConversion() // Sending SDATAC to stop the continuous conversion +{ + waitForLowDRDY(); // SDATAC should be called after DRDY goes LOW (p35. Figure 33) + _spi->transfer(SDATAC); // 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 + + m_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) -{ +void ADS1256::setDRATE(uint8_t drate) // Setting DRATE (sampling frequency) +{ writeRegister(DRATE_REG, drate); - _DRATE = drate; + m_DRATE = drate; delay(200); } -void ADS1256::setMUX(uint8_t mux) //Setting MUX (input channel) -{ +void ADS1256::setMUX(uint8_t mux) // Setting MUX (input channel) +{ writeRegister(MUX_REG, mux); - _MUX = mux; + m_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); +void ADS1256::setPGA(uint8_t pga) // Setting PGA (input voltage range) +{ + m_PGA = pga; + m_ADCON = readRegister(ADCON_REG); // Read the most recent value of the register + + m_ADCON = (m_ADCON & 0b11111000) | (m_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga + + writeRegister(ADCON_REG, m_ADCON); delay(200); - - updateConversionParameter(); //Update the multiplier according top the new PGA value + + 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 +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) + m_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); + // 00 + bitWrite(m_ADCON, 6, 0); + bitWrite(m_ADCON, 5, 0); } - else if(clkout == 1) + else if (clkout == 1) { - //01 (default) - bitWrite(_ADCON, 6, 0); - bitWrite(_ADCON, 5, 1); + // 01 (default) + bitWrite(m_ADCON, 6, 0); + bitWrite(m_ADCON, 5, 1); } - else if(clkout == 2) + else if (clkout == 2) { - //10 - bitWrite(_ADCON, 6, 1); - bitWrite(_ADCON, 5, 0); + // 10 + bitWrite(m_ADCON, 6, 1); + bitWrite(m_ADCON, 5, 0); } - else if(clkout == 3) + else if (clkout == 3) { - //11 - bitWrite(_ADCON, 6, 1); - bitWrite(_ADCON, 5, 1); + // 11 + bitWrite(m_ADCON, 6, 1); + bitWrite(m_ADCON, 5, 1); } - else{} - - writeRegister(ADCON_REG, _ADCON); + else + { + } + + writeRegister(ADCON_REG, m_ADCON); delay(100); } -void ADS1256::setSDCS(uint8_t sdcs) //Setting SDCS +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) + m_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); + // 00 (default) + bitWrite(m_ADCON, 4, 0); + bitWrite(m_ADCON, 3, 0); } - else if(sdcs == 1) + else if (sdcs == 1) { - //01 - bitWrite(_ADCON, 4, 0); - bitWrite(_ADCON, 3, 1); + // 01 + bitWrite(m_ADCON, 4, 0); + bitWrite(m_ADCON, 3, 1); } - else if(sdcs == 2) + else if (sdcs == 2) { - //10 - bitWrite(_ADCON, 4, 1); - bitWrite(_ADCON, 3, 0); + // 10 + bitWrite(m_ADCON, 4, 1); + bitWrite(m_ADCON, 3, 0); } - else if(sdcs == 3) + else if (sdcs == 3) { - //11 - bitWrite(_ADCON, 4, 1); - bitWrite(_ADCON, 3, 1); + // 11 + bitWrite(m_ADCON, 4, 1); + bitWrite(m_ADCON, 3, 1); } - else{} - - writeRegister(ADCON_REG, _ADCON); + else + { + } + + writeRegister(ADCON_REG, m_ADCON); delay(100); } -void ADS1256::setByteOrder(uint8_t byteOrder) //Setting byte order (MSB/LSB) +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) + m_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 + // Byte order is MSB (default) + bitWrite(m_STATUS, 3, 0); + // Set value of _STATUS at the third bit to 0 } - else if(byteOrder == 1) + else if (byteOrder == 1) { - //Byte order is LSB - bitWrite(_STATUS, 3, 1); - //Set value of _STATUS at the third bit to 1 + // Byte order is LSB + bitWrite(m_STATUS, 3, 1); + // Set value of _STATUS at the third bit to 1 } - else{} - - writeRegister(STATUS_REG, _STATUS); + else + { + } + + writeRegister(STATUS_REG, m_STATUS); delay(100); } -uint8_t ADS1256::getByteOrder() //Getting byte order (MSB/LSB) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - +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) +void ADS1256::setAutoCal(uint8_t acal) // Setting ACAL (Automatic SYSCAL) +{ + m_STATUS = readRegister(STATUS_REG); // Read the most recent value of the register + + if (acal == 0) { - //Auto-calibration is disabled (default) - bitWrite(_STATUS, 2, 0); + // Auto-calibration is disabled (default) + bitWrite(m_STATUS, 2, 0); //_STATUS |= B00000000; } - else if(acal == 1) + else if (acal == 1) { - //Auto-calibration is enabled - bitWrite(_STATUS, 2, 1); + // Auto-calibration is enabled + bitWrite(m_STATUS, 2, 1); //_STATUS |= B00000100; } - else{} - - writeRegister(STATUS_REG, _STATUS); + else + { + } + + writeRegister(STATUS_REG, m_STATUS); delay(100); } -uint8_t ADS1256::getAutoCal() //Getting ACAL (Automatic SYSCAL) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - +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) +void ADS1256::setBuffer(uint8_t bufen) // Setting input buffer (Input impedance) +{ + m_STATUS = readRegister(STATUS_REG); // Read the most recent value of the register + + if (bufen == 0) { - //Analog input buffer is disabled (default) + // Analog input buffer is disabled (default) //_STATUS |= B00000000; - bitWrite(_STATUS, 1, 0); + bitWrite(m_STATUS, 1, 0); } - else if(bufen == 1) + else if (bufen == 1) { - //Analog input buffer is enabled (recommended) + // Analog input buffer is enabled (recommended) //_STATUS |= B00000010; - bitWrite(_STATUS, 1, 1); + bitWrite(m_STATUS, 1, 1); } - else{} - - writeRegister(STATUS_REG, _STATUS); + else + { + } + + writeRegister(STATUS_REG, m_STATUS); delay(100); } -uint8_t ADS1256::getBuffer() //Getting input buffer (Input impedance) -{ - uint8_t statusValue = readRegister(STATUS_REG); //Read the whole STATUS register - +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 +void ADS1256::setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3) // Setting GPIO +{ + m_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) + + // Bit7: DIR3 + if (dir3 == 1) { - GPIO_bit7 = 1; //D3 is input (default) + GPIO_bit7 = 1; // D3 is input (default) } else { - GPIO_bit7 = 0; //D3 is output - } - bitWrite(_GPIO, 7, GPIO_bit7); + GPIO_bit7 = 0; // D3 is output + } + bitWrite(m_GPIO, 7, GPIO_bit7); //----------------------------------------------------- - //Bit6: DIR2 - if(dir2 == 1) + // Bit6: DIR2 + if (dir2 == 1) { - GPIO_bit6 = 1; //D2 is input (default) + GPIO_bit6 = 1; // D2 is input (default) } else { - GPIO_bit6 = 0; //D2 is output + GPIO_bit6 = 0; // D2 is output } - bitWrite(_GPIO, 6, GPIO_bit6); + bitWrite(m_GPIO, 6, GPIO_bit6); //----------------------------------------------------- - //Bit5: DIR1 - if(dir1 == 1) + // Bit5: DIR1 + if (dir1 == 1) { - GPIO_bit5 = 1; //D1 is input (default) + GPIO_bit5 = 1; // D1 is input (default) } else { - GPIO_bit5 = 0; //D1 is output + GPIO_bit5 = 0; // D1 is output } - bitWrite(_GPIO, 5, GPIO_bit5); + bitWrite(m_GPIO, 5, GPIO_bit5); //----------------------------------------------------- - //Bit4: DIR0 - if(dir0 == 1) + // Bit4: DIR0 + if (dir0 == 1) { - GPIO_bit4 = 1; //D0 is input + GPIO_bit4 = 1; // D0 is input } else { - GPIO_bit4 = 0; //D0 is output (default) + GPIO_bit4 = 0; // D0 is output (default) } - bitWrite(_GPIO, 4, GPIO_bit4); + bitWrite(m_GPIO, 4, GPIO_bit4); //----------------------------------------------------- - - writeRegister(IO_REG, _GPIO); + + writeRegister(IO_REG, m_GPIO); delay(100); } -void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value) //Writing GPIO +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 - + m_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) + + // Bit3: DIR3 + if (dir3value == 1) { GPIO_bit3 = 1; } else { GPIO_bit3 = 0; - } - bitWrite(_GPIO, 3, GPIO_bit3); + } + bitWrite(m_GPIO, 3, GPIO_bit3); //----------------------------------------------------- - //Bit2: DIR2 - if(dir2value == 1) + // Bit2: DIR2 + if (dir2value == 1) { GPIO_bit2 = 1; } else { GPIO_bit2 = 0; - } - bitWrite(_GPIO, 2, GPIO_bit2); + } + bitWrite(m_GPIO, 2, GPIO_bit2); //----------------------------------------------------- - //Bit1: DIR1 - if(dir1value == 1) + // Bit1: DIR1 + if (dir1value == 1) { GPIO_bit1 = 1; } @@ -407,356 +444,354 @@ void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, { GPIO_bit1 = 0; } - bitWrite(_GPIO, 1, GPIO_bit1); + bitWrite(m_GPIO, 1, GPIO_bit1); //----------------------------------------------------- - //Bit0: DIR0 - if(dir0value == 1) + // Bit0: DIR0 + if (dir0value == 1) { GPIO_bit0 = 1; } else { GPIO_bit0 = 0; - } - bitWrite(_GPIO, 0, GPIO_bit0); - //----------------------------------------------------- - - writeRegister(IO_REG, _GPIO); + } + bitWrite(m_GPIO, 0, GPIO_bit0); + //----------------------------------------------------- + + writeRegister(IO_REG, m_GPIO); delay(100); } -uint8_t ADS1256::readGPIO(uint8_t gpioPin) //Reading GPIO -{ +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 + + m_GPIO = readRegister(IO_REG); // Read the GPIO register + + // Save each bit values in a variable + GPIO_bit3 = bitRead(m_GPIO, 3); + GPIO_bit2 = bitRead(m_GPIO, 2); + GPIO_bit1 = bitRead(m_GPIO, 1); + GPIO_bit0 = bitRead(m_GPIO, 0); + + delay(100); + + switch (gpioPin) // Selecting which value should be returned { - case 0: + case 0: GPIO_return = GPIO_bit0; break; - - case 1: + + case 1: GPIO_return = GPIO_bit1; break; - - case 2: + + case 2: GPIO_return = GPIO_bit2; break; - - case 3: + + 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(SPI_FREQ, MSBFIRST, SPI_MODE1)); + // Direct commands can be found in the datasheet Page 34, Table 24. + _spi->beginTransaction(SPISettings(SPI_FREQ, 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 (m_conversionParameter * rawData); } void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite) -{ - waitForLowDRDY(); - - _spi->beginTransaction(SPISettings(SPI_FREQ, 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] - - delayMicroseconds(5); //see t6 in the datasheet - - _spi->transfer(WREG | registerAddress); // 0x50 = 01010000 = WREG - - _spi->transfer(0x00); //2nd (empty) command byte - - _spi->transfer(registerValueToWrite); //pass the value to the register - - CS_HIGH(); - _spi->endTransaction(); - delay(100); - -} - -long ADS1256::readRegister(uint8_t registerAddress) //Reading a register { - waitForLowDRDY(); - - _spi->beginTransaction(SPISettings(SPI_FREQ, 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(SPI_FREQ, MSBFIRST, SPI_MODE1)); + // SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. - _spi->transfer(RREG | 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 + delayMicroseconds(5); // see t6 in the datasheet - delayMicroseconds(5); //see t6 in the datasheet + _spi->transfer(WREG | registerAddress); // 0x50 = 01010000 = WREG - uint8_t regValue = _spi->transfer(0x00); //read out the register value + _spi->transfer(0x00); // 2nd (empty) command byte - CS_HIGH(); - _spi->endTransaction(); - delay(100); - return regValue; + _spi->transfer(registerValueToWrite); // pass the value to the register + + CS_HIGH(); + _spi->endTransaction(); + delay(100); } +long ADS1256::readRegister(uint8_t registerAddress) // Reading a register +{ + waitForLowDRDY(); -long ADS1256::readSingle() //Reading a single value ONCE using the RDATA command + _spi->beginTransaction(SPISettings(SPI_FREQ, 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] + + _spi->transfer(RREG | registerAddress); // 0x10 = 0001000 = RREG - OR together the two numbers (command + address) + + _spi->transfer(0x00); // 2nd (empty) command byte + + delayMicroseconds(5); // see t6 in the datasheet + + uint8_t regValue = _spi->transfer(0x00); // 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 { _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); - CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" + CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" waitForLowDRDY(); - _spi->transfer(RDATA); //Issue RDATA (0000 0001) command - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. + _spi->transfer(RDATA); // 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 + m_outputBuffer[0] = _spi->transfer(0); // MSB + m_outputBuffer[1] = _spi->transfer(0); // Mid-byte + m_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); - - CS_HIGH(); //We finished the command sequence, so we set CS to HIGH + // Shifting and combining the above three items into a single, 24-bit number + m_outputValue = ((long)m_outputBuffer[0] << 16) | ((long)m_outputBuffer[1] << 8) | (m_outputBuffer[2]); + m_outputValue = convertSigned24BitToLong(m_outputValue); + + CS_HIGH(); // We finished the command sequence, so we set CS to HIGH _spi->endTransaction(); - - return(_outputValue); + + return (m_outputValue); } -long ADS1256::readSingleContinuous() //Reads the recently selected input channel using RDATAC -{ - if(_isAcquisitionRunning == false) +long ADS1256::readSingleContinuous() // Reads the recently selected input channel using RDATAC +{ + if (m_isAcquisitionRunning == false) { - _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); - CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" - waitForLowDRDY(); - _spi->transfer(RDATAC); //Issue RDATAC (0000 0011) - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. + m_isAcquisitionRunning = true; + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); + CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" + waitForLowDRDY(); + _spi->transfer(RDATAC); // 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); - + } + + m_outputBuffer[0] = _spi->transfer(0); // MSB + m_outputBuffer[1] = _spi->transfer(0); // Mid-byte + m_outputBuffer[2] = _spi->transfer(0); // LSB + + m_outputValue = ((long)m_outputBuffer[0] << 16) | ((long)m_outputBuffer[1] << 8) | (m_outputBuffer[2]); + m_outputValue = convertSigned24BitToLong(m_outputValue); + waitForHighDRDY(); - - return _outputValue; + + return m_outputValue; } long ADS1256::cycleSingle() { - if(_isAcquisitionRunning == false) + if (m_isAcquisitionRunning == false) { - _isAcquisitionRunning = true; - _cycle = 0; - _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX - _spi->transfer(0x00); - _spi->transfer(SING_0); //AIN0+AINCOM - delayMicroseconds(250); + m_isAcquisitionRunning = true; + m_cycle = 0; + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); + CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24] + _spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX + _spi->transfer(0x00); + _spi->transfer(SING_0); // AIN0+AINCOM + delayMicroseconds(250); } 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; + if (m_cycle < 8) + { + m_outputValue = 0; + waitForLowDRDY(); + // Step 1. - Updating MUX + switch (m_cycle) + { + // Channels are written manually + case 0: // Channel 2 + updateMUX(SING_1); // AIN1+AINCOM + break; - case 2: //Channel 4 - updateMUX(SING_3); //AIN3+AINCOM - break; + case 1: // Channel 3 + updateMUX(SING_2); // AIN2+AINCOM + break; - case 3: //Channel 5 - updateMUX(SING_4); //AIN4+AINCOM - break; + case 2: // Channel 4 + updateMUX(SING_3); // AIN3+AINCOM + break; - case 4: //Channel 6 - updateMUX(SING_5); //AIN5+AINCOM - break; + case 3: // Channel 5 + updateMUX(SING_4); // AIN4+AINCOM + break; - case 5: //Channel 7 - updateMUX(SING_6); //AIN6+AINCOM - break; + case 4: // Channel 6 + updateMUX(SING_5); // AIN5+AINCOM + break; - case 6: //Channel 8 - updateMUX(SING_7); //AIN7+AINCOM - break; + case 5: // Channel 7 + updateMUX(SING_6); // AIN6+AINCOM + break; - case 7: //Channel 1 - updateMUX(SING_0); //AIN0+AINCOM - break; - } - //Step 2. - _spi->transfer(SYNC); //SYNC - delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(WAKEUP); //WAKEUP + case 6: // Channel 8 + updateMUX(SING_7); // AIN7+AINCOM + break; - //Step 3. - //Issue RDATA (0000 0001) command - _spi->transfer(RDATA); - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. + case 7: // Channel 1 + updateMUX(SING_0); // AIN0+AINCOM + break; + } + // Step 2. + _spi->transfer(SYNC); // SYNC + delayMicroseconds(4); // t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us + _spi->transfer(WAKEUP); // WAKEUP - _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++; //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; + // Step 3. + // Issue RDATA (0000 0001) command + _spi->transfer(RDATA); + delayMicroseconds(7); // Wait t6 time (~6.51 us) REF: P34, FIG:30. + + m_outputBuffer[0] = _spi->transfer(0); // MSB + m_outputBuffer[1] = _spi->transfer(0); // Mid-byte + m_outputBuffer[2] = _spi->transfer(0); // LSB + + m_outputValue = ((long)m_outputBuffer[0] << 16) | ((long)m_outputBuffer[1] << 8) | (m_outputBuffer[2]); + m_outputValue = convertSigned24BitToLong(m_outputValue); + + m_cycle++; // Increase cycle - This will move to the next MUX input channel + if (m_cycle == 8) + { + m_cycle = 0; // Reset to 0 - Restart conversion from the 1st input channel + } + } + + return m_outputValue; } -long ADS1256::cycleDifferential() +long ADS1256::cycleDifferential() { - if(_isAcquisitionRunning == false) + if (m_isAcquisitionRunning == false) { - _cycle = 0; - _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(SPI_FREQ, 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(WREG | MUX_REG); // 0x50 = WREG //1 = MUX - _spi->transfer(0x00); - _spi->transfer(DIFF_0_1); //AIN0+AIN1 - delayMicroseconds(250); + m_cycle = 0; + m_isAcquisitionRunning = true; + _spi->beginTransaction(SPISettings(SPI_FREQ, 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(WREG | MUX_REG); // 0x50 = WREG //1 = MUX + _spi->transfer(0x00); + _spi->transfer(DIFF_0_1); // AIN0+AIN1 + delayMicroseconds(250); } 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; + if (m_cycle < 4) + { + m_outputValue = 0; + // DRDY has to go low + waitForLowDRDY(); - case 1: //Channel 3 - updateMUX(DIFF_4_5); //AIN4+AIN5 - break; + // Step 1. - Updating MUX + switch (m_cycle) + { + case 0: // Channel 2 + updateMUX(DIFF_2_3); // AIN2+AIN3 + break; - case 2: //Channel 4 - updateMUX(DIFF_6_7); //AIN6+AIN7 - break; + case 1: // Channel 3 + updateMUX(DIFF_4_5); // AIN4+AIN5 + break; - case 3: //Channel 1 - updateMUX(DIFF_0_1); //AIN0+AIN1 - break; - } + case 2: // Channel 4 + updateMUX(DIFF_6_7); // AIN6+AIN7 + break; - _spi->transfer(SYNC); //SYNC - delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(WAKEUP); //WAKEUP + case 3: // Channel 1 + updateMUX(DIFF_0_1); // AIN0+AIN1 + break; + } - //Step 3. - _spi->transfer(RDATA); //Issue RDATA (0000 0001) command - delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. + _spi->transfer(SYNC); // SYNC + delayMicroseconds(4); // t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us + _spi->transfer(WAKEUP); // WAKEUP - _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; + // Step 3. + _spi->transfer(RDATA); // Issue RDATA (0000 0001) command + delayMicroseconds(7); // Wait t6 time (~6.51 us) REF: P34, FIG:30. + + m_outputBuffer[0] = _spi->transfer(0); // MSB + m_outputBuffer[1] = _spi->transfer(0); // Mid-byte + m_outputBuffer[2] = _spi->transfer(0); // LSB + + m_outputValue = ((long)m_outputBuffer[0] << 16) | ((long)m_outputBuffer[1] << 8) | (m_outputBuffer[2]); + m_outputValue = convertSigned24BitToLong(m_outputValue); + + m_cycle++; + if (m_cycle == 4) + { + m_cycle = 0; + // After the 4th cycle, we reset to zero so the next iteration reads the 1st MUX again + } + } + + return m_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. + m_conversionParameter = ((2.0 * m_VREF) / 8388608.0) / (pow(2, m_PGA)); // Calculate the "bit to Volts" multiplier + // 8388608 = 2^{23} - 1, REF: p23, Table 16. } void ADS1256::updateMUX(uint8_t muxValue) { - _spi->transfer(WREG | 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(WREG | 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 (m_CS_pin != PIN_UNUSED) // Sets CS LOW if it is not an unused pin { - digitalWrite(_CS_pin, LOW); + digitalWrite(m_CS_pin, LOW); } } inline void ADS1256::CS_HIGH() { - if (_CS_pin != PIN_UNUSED) //Sets CS HIGH if it is not an unused pin + if (m_CS_pin != PIN_UNUSED) // Sets CS HIGH if it is not an unused pin { - digitalWrite(_CS_pin, HIGH); + digitalWrite(m_CS_pin, HIGH); } } \ No newline at end of file diff --git a/RotaxMonitor/lib/ADS1256/ADS1256.h b/RotaxMonitor/lib/ADS1256/ADS1256.h index 35ade99..5670d5a 100644 --- a/RotaxMonitor/lib/ADS1256/ADS1256.h +++ b/RotaxMonitor/lib/ADS1256/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 */ @@ -14,54 +14,55 @@ #define _ADS1256_h #include +#include // SPI Frequency #define SPI_FREQ 1920000 -//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 +// 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 +// 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 +// 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 +#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 +// 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 +// Status register #define BITORDER_MSB 0 #define BITORDER_LSB 1 #define ACAL_DISABLED 0 @@ -69,7 +70,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 @@ -82,7 +83,7 @@ #define FSC1_REG 0x09 #define FSC2_REG 0x0A -//Command definitions +// Command definitions #define WAKEUP 0b00000000 #define RDATA 0b00000001 #define RDATAC 0b00000011 @@ -99,26 +100,30 @@ #define RESET 0b11111110 //---------------------------------------------------------------- - class ADS1256 -{ +{ public: -static constexpr int8_t PIN_UNUSED = -1; + 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 + // 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); + ~ADS1256() + { + vSemaphoreDelete(m_drdyHigh); + vSemaphoreDelete(m_drdyLow); + } + + // 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 + // 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(); @@ -131,62 +136,80 @@ static constexpr int8_t PIN_UNUSED = -1; 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); + uint8_t readGPIO(uint8_t gpioPin); void setCLKOUT(uint8_t clkout); - void setSDCS(uint8_t sdcs); - void sendDirectCommand(uint8_t directCommand); + void setSDCS(uint8_t sdcs); + void sendDirectCommand(uint8_t directCommand); - //Get a single conversion + // Get a single conversion long readSingle(); - - //Single input continuous reading + + // 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 + + // 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 + + // Stop AD void stopConversion(); - + + // functions for callback + inline uint8_t getDRDYpin() + { + return m_DRDY_pin; + } + + SemaphoreHandle_t getDRDYsemaphoreHigh() + { + return m_drdyHigh; + } + + SemaphoreHandle_t getDRDYsemaphoreLow() + { + return m_drdyLow; + } + private: - -SPIClass* _spi; //Pointer to an SPIClass object + 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 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 + 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 + float m_VREF = 0; // Value of the reference voltage + float m_conversionParameter = 0; // PGA-dependent multiplier + // Pins + int8_t m_DRDY_pin; // Pin assigned for DRDY + int8_t m_RESET_pin; // Pin assigned for RESET + int8_t m_SYNC_pin; // Pin assigned for SYNC + int8_t m_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 + // Register values + uint8_t m_DRATE; // Value of the DRATE register + uint8_t m_ADCON; // Value of the ADCON register + uint8_t m_MUX; // Value of the MUX register + uint8_t m_PGA; // Value of the PGA (within ADCON) + uint8_t m_GPIO; // Value of the GPIO register + uint8_t m_STATUS; // Value of the status register + uint8_t m_GPIOvalue; // GPIO value + uint8_t m_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 + uint8_t m_outputBuffer[3]; // 3-byte (24-bit) buffer for the fast acquisition - Single-channel, continuous + int32_t m_outputValue; // Combined value of the m_outputBuffer[3] + bool m_isAcquisitionRunning; // bool that keeps track of the acquisition (running or not) + uint8_t m_cycle; // Tracks the cycles as the MUX is cycling through the input channels + + SemaphoreHandle_t m_drdyHigh; + SemaphoreHandle_t m_drdyLow; }; #endif \ No newline at end of file diff --git a/RotaxMonitor/src/main.cpp b/RotaxMonitor/src/main.cpp index 7ae1830..cd46365 100644 --- a/RotaxMonitor/src/main.cpp +++ b/RotaxMonitor/src/main.cpp @@ -131,35 +131,6 @@ void loop() #endif LOG_DEBUG("Init SPI OK"); - uint8_t chs[8] = { - SING_0, SING_1, SING_2, SING_3, SING_4, SING_5, SING_6, SING_7}; - float res[8]; - auto timeout = Serial.getTimeout(); - Serial.setTimeout(0); - uint64_t count = 0; - - while (Serial.read() != 's') // The conversion is stopped by a character received from the serial port - { - auto start = esp_timer_get_time(); - for (int i = 0; i < 8; i++) - { - // dev->m_adc_a->setMUX(chs[i]); - res[i] += 0.1f * (dev->m_adc_a->convertToVoltage(dev->m_adc_a->cycleSingle()) - res[i]); - } - auto stop = esp_timer_get_time(); - if (count++ % 25 == 0) - { - clearScreen(); - for (int j = 0; j < 8; j++) - { - Serial.printf("ADC_A SING_%d: %5.4f\n", j, res[j]); - } - Serial.printf("ADC Time: %5.3f ms\n", (float)((stop - start) / 1000.0f)); - } - } - Serial.setTimeout(timeout); - dev->m_adc_a->stopConversion(); - //////// INIT I2C INTERFACES //////// LOG_DEBUG("Init I2C Interfaces"); bool i2c_ok = true;