Skip to content
This repository was archived by the owner on Jul 23, 2020. It is now read-only.

Modify registers #2

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
27 changes: 7 additions & 20 deletions flowi2chelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,19 @@
bool I2CHelper::readFromI2C(uint8_t i2cAddress, const uint8_t* i2cCommand, uint8_t commandLength, uint8_t* data, uint8_t dataLength)
{
Wire.beginTransmission(i2cAddress);
for (int i = 0; i < commandLength; ++i) {
if (Wire.write(i2cCommand[i]) != 1) {
return false;
}
}
if (Wire.endTransmission(false) != 0) {
Serial.println("NACK");
Wire.write(i2cCommand, commandLength);
if (Wire.endTransmission(0 == dataLength) != 0) {
return false;
}

Wire.requestFrom(i2cAddress, dataLength);
if (dataLength != 0) {
if (dataLength > Wire.requestFrom(i2cAddress, dataLength))
return false;

// there should be no reason for this to not be ready, since we're using clock stretching mode,
// but just in case we'll try a few times
uint8_t tries = 1;
while (Wire.available() < dataLength) {
delay(1);
if (tries++ >= MAX_READ_TRIES) {
return false;
for (int i = 0; i < dataLength; ++i) {
data[i] = Wire.read();
}
}

for (int i = 0; i < dataLength; ++i) {
data[i] = Wire.read();
}
return true;
}


78 changes: 64 additions & 14 deletions sensirionflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,43 @@ SensirionFlow::SensirionFlow(uint8_t i2cAddress)
{
}

void SensirionFlow::init()
bool SensirionFlow::init()
{
const uint8_t CMD_LENGTH = 1;
const uint8_t CMD_READ_USER_REGISTER[CMD_LENGTH] = { 0xE3 };
const uint8_t DATA_LENGTH = 6; // 2 data, 1 crc
uint8_t data[DATA_LENGTH];

// - read user register
if (!I2CHelper::readFromI2C(mI2cAddress, CMD_READ_USER_REGISTER, CMD_LENGTH, data, 3)) {
Serial.print("Failed to read from I2C 1\n");
return;
register_value_t baseAddress;
if (!readRegister(user_reg, &baseAddress)) {
return false;
}

int16_t baseAddress = (data[0] << 8) + data[1];

baseAddress &= 0x70; // EEPROM base address is bits <6..4>
baseAddress >>= 4;
baseAddress *= 0x300;

// - read scale factor
int16_t scaleFactorAddress = (baseAddress + 0x02B6);
uint16_t scaleFactorAddress = (baseAddress + 0x02B6);
scaleFactorAddress <<= 4; // address is a left aligned 12-bit value

uint8_t cmdReadRegister[] = { 0xFA, (scaleFactorAddress >> 8), scaleFactorAddress & 0x00FF };
uint8_t cmdReadRegister[] = { 0xFA, (uint8_t)(scaleFactorAddress >> 8), (uint8_t)(scaleFactorAddress & 0x00FF) };
if (!I2CHelper::readFromI2C(mI2cAddress, cmdReadRegister, 3, data, DATA_LENGTH)) {
Serial.print("Failed to read from I2C 2\n");
return;
return false;
}
mScaleFactor = (data[0] << 8) + data[1]; // data[2] = crc

uint16_t measurementUnit = (data[3] << 8) + data[4]; // data[2] = crc
mDimension = measurementUnit & 0xF;
mTimeBase = (measurementUnit >> 4) & 0xF;
mVolumePressureUnit = (measurementUnit >> 8) & 0x1F;
return true;
}

void SensirionFlow::reset()
{
const uint8_t CMD_LENGTH = 1;
const uint8_t CMD_RESET[CMD_LENGTH] = { 0xFE };
I2CHelper::readFromI2C(mI2cAddress, CMD_RESET, CMD_LENGTH, NULL, 0);
}

float SensirionFlow::readSample()
Expand All @@ -85,12 +89,58 @@ float SensirionFlow::readSample()
uint8_t data[dataLength];

command[0] = 0xF1;
if (!I2CHelper::readFromI2C(mI2cAddress, command, 1, data, dataLength)) {
Serial.print("Failed to read from I2C 4\n");
if (!I2CHelper::readFromI2C(mI2cAddress, command, cmdLength, data, dataLength)) {
return 0;
}

float measurementValue = ((data[0] << 8) + data[1]);
return (measurementValue / mScaleFactor);
}

bool SensirionFlow::readRegister(register_id_t reg, register_value_t *buffer)
{
const static uint8_t commands[] = { 0xE3, 0xE5, 0xE7, 0xE9 };
const uint8_t dataLength = 2;

if (reg >= 4) {
return false;
}

uint8_t data[dataLength];

if (!I2CHelper::readFromI2C(mI2cAddress, &commands[reg], 1, data, dataLength)) {
return false;
}

*buffer = (data[0] << 8) | data[1];
return true;
}

bool SensirionFlow::writeRegister(register_id_t reg, register_value_t data)
{
const static uint8_t commands[] = { 0xE2, 0xE4 };
const uint8_t commandLength = 3;

if (reg >= 2){
return false;
}

uint8_t command[commandLength];
command[0] = commands[reg];
command[1] = data >> 8;
command[2] = data & 0x00FF;

return I2CHelper::readFromI2C(mI2cAddress, &command[0], commandLength, NULL, 0);
}

bool SensirionFlow::modifyRegister(register_id_t reg, register_value_t data, register_value_t mask)
{
register_value_t value;
if (!readRegister(reg, &value)) {
return false;
}

value &= ~mask; // zero out bits to modify
value |= data & mask; // set 1-bits to modify
return writeRegister(reg, value);
}
21 changes: 18 additions & 3 deletions sensirionflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,29 @@ class SensirionFlow
{
public:
SensirionFlow(uint8_t i2cAddress);
void init();

bool init();
void reset();

float readSample();

uint8_t getDimension() const { return mDimension; };
uint8_t getTimeBase() const { return mTimeBase; };
uint8_t getVolumePressureUnit() const { return mVolumePressureUnit; };


typedef enum
{
user_reg = 0,
adv_user_reg,
readonly_1,
readonly_2
} register_id_t;

typedef uint16_t register_value_t;

bool readRegister(register_id_t reg, register_value_t *buffer);
bool writeRegister(register_id_t reg, register_value_t data);
bool modifyRegister(register_id_t reg, register_value_t data, register_value_t mask);

private:
uint8_t mI2cAddress;
int16_t mScaleFactor;
Expand Down