Apologies for the long read, I am trying to learn and make sense of this as I go. I am trying to use a SDC40 sensor over I2C to read CO2, temperature, and humidity. Originally I thought my errors may have been a conflict with an existing instance of Wire, however, the example sketch provided within the library "Sensirion I2C SCD4x" by Sensirion wont compile either.
If I switch the board from Arduino Uno WiFi Rev2 to something in the AVR range such as the standard Arduino Uno Wifi then everything compiles just fine. I am assuming something with the megaAVR boards conflicts with how this sensor expects to use I2C.
Compilation Errors:
In file included from C:\Users\d4sturt\Documents\Arduino\libraries\Sensirion_Core\src\SensirionI2CCommunication.h:38:0,
from C:\Users\d4sturt\Documents\Arduino\libraries\Sensirion_Core\src\SensirionI2CCommunication.cpp:31:
C:\Users\d4sturt\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.8\libraries\Wire\src/Wire.h: In static member function 'static uint16_t SensirionI2CCommunication::receiveFrame(uint8_t, size_t, SensirionI2CRxFrame&, TwoWire&, CrcPolynomial)':
C:\Users\d4sturt\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.8\libraries\Wire\src/Wire.h:64:12: note: candidate 1: size_t TwoWire::requestFrom(int, int, int)
size_t requestFrom(int, int, int);
^~~~~~~~~~~
C:\Users\d4sturt\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.8\libraries\Wire\src/Wire.h:62:12: note: candidate 2: virtual size_t TwoWire::requestFrom(uint8_t, size_t, bool)
size_t requestFrom(uint8_t, size_t, bool);
^~~~~~~~~~~
When I look into the Class found in "SensirionI2CCommunication.h" I see:
class SensirionI2CCommunication {
public:
static uint16_t sendFrame(uint8_t address, SensirionI2CTxFrame& frame,
TwoWire& i2cBus);
static uint16_t receiveFrame(uint8_t address, size_t numBytes,
SensirionI2CRxFrame& frame, TwoWire& i2cBus,
CrcPolynomial poly = CRC31_ff);
};
The sensor is supposed to return CO2, temperature, and humidity. In the sketch they are defined as uint16_t, float, and float respectively. Looking at the function which handles sending/receiving I can see that all values are declared as uint16_t and then later converted to match the expected data types:
uint16_t SensirionI2CScd4x::readMeasurementTicks(uint16_t& co2,
uint16_t& temperature,
uint16_t& humidity) {
uint16_t error;
uint8_t buffer[9];
SensirionI2CTxFrame txFrame(buffer, 9);
error = txFrame.addCommand(0xEC05);
if (error) {
return error;
}
error = SensirionI2CCommunication::sendFrame(SCD4X_I2C_ADDRESS, txFrame,
*_i2cBus);
if (error) {
return error;
}
delay(1);
SensirionI2CRxFrame rxFrame(buffer, 9);
error = SensirionI2CCommunication::receiveFrame(SCD4X_I2C_ADDRESS, 9,
rxFrame, *_i2cBus);
if (error) {
return error;
}
error |= rxFrame.getUInt16(co2);
error |= rxFrame.getUInt16(temperature);
error |= rxFrame.getUInt16(humidity);
return error;
}
uint16_t SensirionI2CScd4x::readMeasurement(uint16_t& co2, float& temperature,
float& humidity) {
uint16_t error;
uint16_t temperatureTicks;
uint16_t humidityTicks;
error = readMeasurementTicks(co2, temperatureTicks, humidityTicks);
if (error) {
return error;
}
temperature = static_cast<float>(temperatureTicks * 175.0 / 65535.0 - 45.0);
humidity = static_cast<float>(humidityTicks * 100.0 / 65535.0);
return NoError;
}
If I am interpreting the errors correctly then Wire is expecting the result to be all integers as referenced as the first candidate in the error description, while Sensirion is expecting all uint16_t's.
I am also going to assume that the second candidate in the output window is only for a single frame of data (uint8_t, size_t, bool). Not sure if this is correct with my limited knowledge of how Wire and I2C work.
At this point I do not know what to change or if using this sensor is even feasible. Please let me know if there is any additional detail needed or more importantly...a solution.