Library to read/write Sensirion SF04 based gas/liquid flow sensors.

Dependents:   TestBenchSerenity-proto_F429ZI TestBenchFlow HSPFLOW1 TestBenchFlow1 ... more

sensirion_sf04.h

Committer:
dmwahl
Date:
2021-09-16
Revision:
7:0c1bbd80bec3
Parent:
4:edf2c4870bbf

File content as of revision 7:0c1bbd80bec3:

/// Start of sample code--------------------------------------------------------
/*
#include "mbed.h"
#include "sensirion_sf04.h"

#define SFM7033_ADDR 0x40

// an I2C sub-class that provides a constructed default
class I2CPreInit : public I2C
{
public:
    I2CPreInit(PinName sda, PinName scl, int freq) : I2C(sda, scl) {
        frequency(freq);
        //start();
    };
};

//I2CPreInit gI2C1(I2C_SDA, I2C_SCL, I2C frequency);
//I2CPreInit gI2C1(PB_9, PB_8, 100000);
I2CPreInit gI2C2(PB_3, PB_10, 100000);
//I2CPreInit gI2C3(PB_4, PA_8);

// (I2C object, address, cal field(0-4), resolution(9-16bit))
SF04 sfm(gI2C2, SFM7033_ADDR, 0, 16);

DigitalOut myled(LED1);
Serial pc(SERIAL_TX, SERIAL_RX);

int main()
{
    pc.baud(250000);
    pc.printf("Starting up...\n\r");

    pc.printf("SN: %u Scale: %d Unit:%s\n\r", sfm.serialNumber.u32, sfm.scaleFactor.u16, sfm.flowUnitStr);
    
    //wait(3);
    while (1) {
        myled = !myled;
        wait(1.0);
        
        sfm.Measure(FLOW);
        sfm.Measure(TEMP);
        sfm.Measure(VDD);
        pc.printf("%.0f %s (raw: %u) Temp: %.1fC Vdd: %.2f\n\r", ((float)sfm.flow.i16 / sfm.scaleFactor.u16), sfm.flowUnitStr, sfm.flow.u16, (float)sfm.temperature.i16/10, (float)sfm.vdd.u16/1000);
    }
}
*/
/// End sample code-------------------------------------------------------------
#ifndef SENSIRION_SF04_H
#define SENSIRION_SF04_H

#include "mbed.h"
#include "sensirion_sf04_typedefs.h"

#define I2C_READ 1
#define I2C_WRITE 0

//---------- Defines -----------------------------------------------------------
// CRC
#define SF04_POLYNOMIAL 0x131 //P(x)=x^8+x^5+x^4+1 = 100110001

// SF04 eeprom map
#define SF04_EE_ADR_SN_CHIP 0x02E4
#define SF04_EE_ADR_SN_PRODUCT 0x02F8
#define SF04_EE_ADR_SCALE_FACTOR 0x02B6
#define SF04_EE_ADR_FLOW_UNIT 0x02B7

// sensor command
typedef enum {
    SF04_USER_REG_W = 0xE2, // command writing user register
    SF04_USER_REG_R = 0xE3, // command reading user register
    SF04_ADV_USER_REG_W = 0xE4, // command writing advanced user register
    SF04_ADV_USER_REG_R = 0xE5, // command reading advanced user register
    SF04_READ_ONLY_REG1_R = 0xE7, // command reading read-only register 1
    SF04_READ_ONLY_REG2_R = 0xE9, // command reading read-only register 2
    SF04_TRIGGER_FLOW_MEASUREMENT = 0xF1, // command trig. a flow measurement
    SF04_TRIGGER_TEMP_MEASUREMENT = 0xF3, // command trig. a temperature measurement
    SF04_TRIGGER_VDD_MEASUREMENT = 0xF5, // command trig. a supply voltage measurement
    SF04_EEPROM_W = 0xFA, // command writing eeprom
    SF04_EEPROM_R = 0xFA, // command reading eeprom
    SF04_SOFT_RESET = 0xFE // command soft reset
} etCommand;

// sensor register
typedef enum {
    SF04_USER_REG = SF04_USER_REG_R,
    SF04_ADV_USER_REG = SF04_ADV_USER_REG_R,
    SF04_READ_ONLY_REG1 = SF04_READ_ONLY_REG1_R,
    SF04_READ_ONLY_REG2 = SF04_READ_ONLY_REG2_R
} etSF04Register;

// measurement signal selection
typedef enum {
    FLOW = SF04_TRIGGER_FLOW_MEASUREMENT,
    TEMP = SF04_TRIGGER_TEMP_MEASUREMENT,
    VDD = SF04_TRIGGER_VDD_MEASUREMENT,
} etSF04MeasureType;

// This enum lists all available flow resolution (Advanced User Register [11:9])
typedef enum {
    eSF04_RES_9BIT = ( 0<<9 ),
    eSF04_RES_10BIT = ( 1<<9 ),
    eSF04_RES_11BIT = ( 2<<9 ),
    eSF04_RES_12BIT = ( 3<<9 ),
    eSF04_RES_13BIT = ( 4<<9 ),
    eSF04_RES_14BIT = ( 5<<9 ),
    eSF04_RES_15BIT = ( 6<<9 ),
    eSF04_RES_16BIT = ( 7<<9 ),
    eSF04_RES_MASK = ( 7<<9 ) // (0x0E00)
} etSF04Resolution;

// Error codes
typedef enum {
    SF04_ACK_ERROR = 0x01,
    SF04_TIME_OUT_ERROR = 0x02,
    SF04_CHECKSUM_ERROR = 0x04,
    SF04_UNIT_ERROR = 0x08
} etError;

// Calibration fields for different gases
typedef enum {
    eSF04_CF0_AIR = 0x0A00,
    eSF04_CF1_O2 = 0x0A10,
    eSF04_CF2_N2O = 0x0A20,
    eSF04_CF3_O2 = 0x0A30, // Only for concentration measurement
    eSF04_CF4_N2O = 0x0A40, // Only for concentration measurement
    eSF04_CFRAW = 0x0880, // Only for concentration measurement
    eSF04_CF_MASK = 0x70
} etSF04Calibration;

// Macro that returns number of elements in an array
#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

class SF04
{
protected:
    I2C &i2c;
    u8t mi2cAddress; // 7-bit I2C address shifted left 1 bit

    u8t checkCRC(u8t data[], u8t numBytes, u8t checksum); // return true if checksum is good, else return false

    u8t ReadRegister(etSF04Register eSF04Register, nt16 *pRegisterValue);
    u8t WriteRegister(etSF04Register eSF04Register, nt16 *pRegisterValue);
    u8t ReadEeprom(u16t eepromStartAdr, u16t size, nt16 eepromData[]);
    u8t ReadSerialNumber(nt32 *serialNumber);
    u8t ReadScaleFactor(nt16 *scaleFactor);
    u8t ReadFlowUnit(char *flowUnitStr);
    u8t setTempVddCorrectionBit(u8t value);


public:
    SF04(I2C &i2c, int addr, int calField, int resolution);
    bool softReset(); // Reset sensor. Return true if slave sends ACK, false if not.

    u8t setMeasResolution(u16t resolution); // Set measurement resolution from 9-16 bits
    u8t setCalibrationField(u8t calfield); // Set active calibration field

    nt32 serialNumber;
    nt16 scaleFactor;
    char flowUnitStr[15]; //string for the flow unit

    // Measure FLOW, TEMP, or VDD
    u8t Measure(etSF04MeasureType eSF04MeasureType);
    nt16 flow, temperature, vdd, status, checksum; // raw readings
    
    bool ready; // signal whether or not an operation is in progress
};

#endif