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

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

Committer:
dmwahl
Date:
Thu Sep 16 20:46:51 2021 +0000
Revision:
7:0c1bbd80bec3
Parent:
4:edf2c4870bbf
Added static_cast<char>(____) to line 188 of sensirion_sf04.cpp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dmwahl 1:e2ad8ac3cdb7 1 /// Start of sample code--------------------------------------------------------
dmwahl 1:e2ad8ac3cdb7 2 /*
dmwahl 1:e2ad8ac3cdb7 3 #include "mbed.h"
dmwahl 1:e2ad8ac3cdb7 4 #include "sensirion_sf04.h"
dmwahl 1:e2ad8ac3cdb7 5
dmwahl 1:e2ad8ac3cdb7 6 #define SFM7033_ADDR 0x40
dmwahl 1:e2ad8ac3cdb7 7
dmwahl 1:e2ad8ac3cdb7 8 // an I2C sub-class that provides a constructed default
dmwahl 1:e2ad8ac3cdb7 9 class I2CPreInit : public I2C
dmwahl 1:e2ad8ac3cdb7 10 {
dmwahl 1:e2ad8ac3cdb7 11 public:
dmwahl 1:e2ad8ac3cdb7 12 I2CPreInit(PinName sda, PinName scl, int freq) : I2C(sda, scl) {
dmwahl 1:e2ad8ac3cdb7 13 frequency(freq);
dmwahl 1:e2ad8ac3cdb7 14 //start();
dmwahl 1:e2ad8ac3cdb7 15 };
dmwahl 1:e2ad8ac3cdb7 16 };
dmwahl 1:e2ad8ac3cdb7 17
dmwahl 1:e2ad8ac3cdb7 18 //I2CPreInit gI2C1(I2C_SDA, I2C_SCL, I2C frequency);
dmwahl 2:67b7c9defdfc 19 //I2CPreInit gI2C1(PB_9, PB_8, 100000);
dmwahl 2:67b7c9defdfc 20 I2CPreInit gI2C2(PB_3, PB_10, 100000);
dmwahl 1:e2ad8ac3cdb7 21 //I2CPreInit gI2C3(PB_4, PA_8);
dmwahl 1:e2ad8ac3cdb7 22
dmwahl 2:67b7c9defdfc 23 // (I2C object, address, cal field(0-4), resolution(9-16bit))
dmwahl 2:67b7c9defdfc 24 SF04 sfm(gI2C2, SFM7033_ADDR, 0, 16);
dmwahl 2:67b7c9defdfc 25
dmwahl 1:e2ad8ac3cdb7 26 DigitalOut myled(LED1);
dmwahl 1:e2ad8ac3cdb7 27 Serial pc(SERIAL_TX, SERIAL_RX);
dmwahl 1:e2ad8ac3cdb7 28
dmwahl 1:e2ad8ac3cdb7 29 int main()
dmwahl 1:e2ad8ac3cdb7 30 {
dmwahl 1:e2ad8ac3cdb7 31 pc.baud(250000);
dmwahl 1:e2ad8ac3cdb7 32 pc.printf("Starting up...\n\r");
dmwahl 1:e2ad8ac3cdb7 33
dmwahl 2:67b7c9defdfc 34 pc.printf("SN: %u Scale: %d Unit:%s\n\r", sfm.serialNumber.u32, sfm.scaleFactor.u16, sfm.flowUnitStr);
dmwahl 1:e2ad8ac3cdb7 35
dmwahl 2:67b7c9defdfc 36 //wait(3);
dmwahl 1:e2ad8ac3cdb7 37 while (1) {
dmwahl 1:e2ad8ac3cdb7 38 myled = !myled;
dmwahl 1:e2ad8ac3cdb7 39 wait(1.0);
dmwahl 1:e2ad8ac3cdb7 40
dmwahl 1:e2ad8ac3cdb7 41 sfm.Measure(FLOW);
dmwahl 1:e2ad8ac3cdb7 42 sfm.Measure(TEMP);
dmwahl 1:e2ad8ac3cdb7 43 sfm.Measure(VDD);
dmwahl 3:2d43f6ceeca9 44 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);
dmwahl 1:e2ad8ac3cdb7 45 }
dmwahl 1:e2ad8ac3cdb7 46 }
dmwahl 1:e2ad8ac3cdb7 47 */
dmwahl 1:e2ad8ac3cdb7 48 /// End sample code-------------------------------------------------------------
dmwahl 0:9e74b14299fd 49 #ifndef SENSIRION_SF04_H
dmwahl 0:9e74b14299fd 50 #define SENSIRION_SF04_H
dmwahl 0:9e74b14299fd 51
dmwahl 0:9e74b14299fd 52 #include "mbed.h"
dmwahl 0:9e74b14299fd 53 #include "sensirion_sf04_typedefs.h"
dmwahl 0:9e74b14299fd 54
dmwahl 0:9e74b14299fd 55 #define I2C_READ 1
dmwahl 0:9e74b14299fd 56 #define I2C_WRITE 0
dmwahl 0:9e74b14299fd 57
dmwahl 0:9e74b14299fd 58 //---------- Defines -----------------------------------------------------------
dmwahl 0:9e74b14299fd 59 // CRC
dmwahl 0:9e74b14299fd 60 #define SF04_POLYNOMIAL 0x131 //P(x)=x^8+x^5+x^4+1 = 100110001
dmwahl 0:9e74b14299fd 61
dmwahl 0:9e74b14299fd 62 // SF04 eeprom map
dmwahl 0:9e74b14299fd 63 #define SF04_EE_ADR_SN_CHIP 0x02E4
dmwahl 0:9e74b14299fd 64 #define SF04_EE_ADR_SN_PRODUCT 0x02F8
dmwahl 0:9e74b14299fd 65 #define SF04_EE_ADR_SCALE_FACTOR 0x02B6
dmwahl 0:9e74b14299fd 66 #define SF04_EE_ADR_FLOW_UNIT 0x02B7
dmwahl 0:9e74b14299fd 67
dmwahl 0:9e74b14299fd 68 // sensor command
dmwahl 0:9e74b14299fd 69 typedef enum {
dmwahl 0:9e74b14299fd 70 SF04_USER_REG_W = 0xE2, // command writing user register
dmwahl 0:9e74b14299fd 71 SF04_USER_REG_R = 0xE3, // command reading user register
dmwahl 0:9e74b14299fd 72 SF04_ADV_USER_REG_W = 0xE4, // command writing advanced user register
dmwahl 0:9e74b14299fd 73 SF04_ADV_USER_REG_R = 0xE5, // command reading advanced user register
dmwahl 0:9e74b14299fd 74 SF04_READ_ONLY_REG1_R = 0xE7, // command reading read-only register 1
dmwahl 0:9e74b14299fd 75 SF04_READ_ONLY_REG2_R = 0xE9, // command reading read-only register 2
dmwahl 0:9e74b14299fd 76 SF04_TRIGGER_FLOW_MEASUREMENT = 0xF1, // command trig. a flow measurement
dmwahl 0:9e74b14299fd 77 SF04_TRIGGER_TEMP_MEASUREMENT = 0xF3, // command trig. a temperature measurement
dmwahl 0:9e74b14299fd 78 SF04_TRIGGER_VDD_MEASUREMENT = 0xF5, // command trig. a supply voltage measurement
dmwahl 0:9e74b14299fd 79 SF04_EEPROM_W = 0xFA, // command writing eeprom
dmwahl 0:9e74b14299fd 80 SF04_EEPROM_R = 0xFA, // command reading eeprom
dmwahl 0:9e74b14299fd 81 SF04_SOFT_RESET = 0xFE // command soft reset
dmwahl 0:9e74b14299fd 82 } etCommand;
dmwahl 0:9e74b14299fd 83
dmwahl 0:9e74b14299fd 84 // sensor register
dmwahl 0:9e74b14299fd 85 typedef enum {
dmwahl 0:9e74b14299fd 86 SF04_USER_REG = SF04_USER_REG_R,
dmwahl 0:9e74b14299fd 87 SF04_ADV_USER_REG = SF04_ADV_USER_REG_R,
dmwahl 0:9e74b14299fd 88 SF04_READ_ONLY_REG1 = SF04_READ_ONLY_REG1_R,
dmwahl 0:9e74b14299fd 89 SF04_READ_ONLY_REG2 = SF04_READ_ONLY_REG2_R
dmwahl 0:9e74b14299fd 90 } etSF04Register;
dmwahl 0:9e74b14299fd 91
dmwahl 0:9e74b14299fd 92 // measurement signal selection
dmwahl 0:9e74b14299fd 93 typedef enum {
dmwahl 0:9e74b14299fd 94 FLOW = SF04_TRIGGER_FLOW_MEASUREMENT,
dmwahl 0:9e74b14299fd 95 TEMP = SF04_TRIGGER_TEMP_MEASUREMENT,
dmwahl 0:9e74b14299fd 96 VDD = SF04_TRIGGER_VDD_MEASUREMENT,
dmwahl 0:9e74b14299fd 97 } etSF04MeasureType;
dmwahl 0:9e74b14299fd 98
dmwahl 0:9e74b14299fd 99 // This enum lists all available flow resolution (Advanced User Register [11:9])
dmwahl 0:9e74b14299fd 100 typedef enum {
dmwahl 0:9e74b14299fd 101 eSF04_RES_9BIT = ( 0<<9 ),
dmwahl 0:9e74b14299fd 102 eSF04_RES_10BIT = ( 1<<9 ),
dmwahl 0:9e74b14299fd 103 eSF04_RES_11BIT = ( 2<<9 ),
dmwahl 0:9e74b14299fd 104 eSF04_RES_12BIT = ( 3<<9 ),
dmwahl 0:9e74b14299fd 105 eSF04_RES_13BIT = ( 4<<9 ),
dmwahl 0:9e74b14299fd 106 eSF04_RES_14BIT = ( 5<<9 ),
dmwahl 0:9e74b14299fd 107 eSF04_RES_15BIT = ( 6<<9 ),
dmwahl 0:9e74b14299fd 108 eSF04_RES_16BIT = ( 7<<9 ),
dmwahl 0:9e74b14299fd 109 eSF04_RES_MASK = ( 7<<9 ) // (0x0E00)
dmwahl 0:9e74b14299fd 110 } etSF04Resolution;
dmwahl 0:9e74b14299fd 111
dmwahl 0:9e74b14299fd 112 // Error codes
dmwahl 0:9e74b14299fd 113 typedef enum {
dmwahl 0:9e74b14299fd 114 SF04_ACK_ERROR = 0x01,
dmwahl 0:9e74b14299fd 115 SF04_TIME_OUT_ERROR = 0x02,
dmwahl 0:9e74b14299fd 116 SF04_CHECKSUM_ERROR = 0x04,
dmwahl 0:9e74b14299fd 117 SF04_UNIT_ERROR = 0x08
dmwahl 0:9e74b14299fd 118 } etError;
dmwahl 0:9e74b14299fd 119
dmwahl 0:9e74b14299fd 120 // Calibration fields for different gases
dmwahl 0:9e74b14299fd 121 typedef enum {
dmwahl 0:9e74b14299fd 122 eSF04_CF0_AIR = 0x0A00,
dmwahl 0:9e74b14299fd 123 eSF04_CF1_O2 = 0x0A10,
dmwahl 0:9e74b14299fd 124 eSF04_CF2_N2O = 0x0A20,
dmwahl 0:9e74b14299fd 125 eSF04_CF3_O2 = 0x0A30, // Only for concentration measurement
dmwahl 0:9e74b14299fd 126 eSF04_CF4_N2O = 0x0A40, // Only for concentration measurement
dmwahl 0:9e74b14299fd 127 eSF04_CFRAW = 0x0880, // Only for concentration measurement
dmwahl 2:67b7c9defdfc 128 eSF04_CF_MASK = 0x70
dmwahl 0:9e74b14299fd 129 } etSF04Calibration;
dmwahl 0:9e74b14299fd 130
dmwahl 0:9e74b14299fd 131 // Macro that returns number of elements in an array
dmwahl 0:9e74b14299fd 132 #define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
dmwahl 0:9e74b14299fd 133
dmwahl 0:9e74b14299fd 134 class SF04
dmwahl 0:9e74b14299fd 135 {
dmwahl 0:9e74b14299fd 136 protected:
dmwahl 0:9e74b14299fd 137 I2C &i2c;
dmwahl 0:9e74b14299fd 138 u8t mi2cAddress; // 7-bit I2C address shifted left 1 bit
dmwahl 0:9e74b14299fd 139
dmwahl 0:9e74b14299fd 140 u8t checkCRC(u8t data[], u8t numBytes, u8t checksum); // return true if checksum is good, else return false
dmwahl 0:9e74b14299fd 141
dmwahl 0:9e74b14299fd 142 u8t ReadRegister(etSF04Register eSF04Register, nt16 *pRegisterValue);
dmwahl 0:9e74b14299fd 143 u8t WriteRegister(etSF04Register eSF04Register, nt16 *pRegisterValue);
dmwahl 0:9e74b14299fd 144 u8t ReadEeprom(u16t eepromStartAdr, u16t size, nt16 eepromData[]);
dmwahl 0:9e74b14299fd 145 u8t ReadSerialNumber(nt32 *serialNumber);
dmwahl 0:9e74b14299fd 146 u8t ReadScaleFactor(nt16 *scaleFactor);
dmwahl 0:9e74b14299fd 147 u8t ReadFlowUnit(char *flowUnitStr);
dmwahl 2:67b7c9defdfc 148 u8t setTempVddCorrectionBit(u8t value);
dmwahl 0:9e74b14299fd 149
dmwahl 0:9e74b14299fd 150
dmwahl 0:9e74b14299fd 151 public:
dmwahl 2:67b7c9defdfc 152 SF04(I2C &i2c, int addr, int calField, int resolution);
dmwahl 2:67b7c9defdfc 153 bool softReset(); // Reset sensor. Return true if slave sends ACK, false if not.
dmwahl 2:67b7c9defdfc 154
dmwahl 2:67b7c9defdfc 155 u8t setMeasResolution(u16t resolution); // Set measurement resolution from 9-16 bits
dmwahl 2:67b7c9defdfc 156 u8t setCalibrationField(u8t calfield); // Set active calibration field
dmwahl 2:67b7c9defdfc 157
dmwahl 0:9e74b14299fd 158 nt32 serialNumber;
dmwahl 0:9e74b14299fd 159 nt16 scaleFactor;
dmwahl 0:9e74b14299fd 160 char flowUnitStr[15]; //string for the flow unit
dmwahl 2:67b7c9defdfc 161
dmwahl 2:67b7c9defdfc 162 // Measure FLOW, TEMP, or VDD
dmwahl 0:9e74b14299fd 163 u8t Measure(etSF04MeasureType eSF04MeasureType);
dmwahl 0:9e74b14299fd 164 nt16 flow, temperature, vdd, status, checksum; // raw readings
dmwahl 4:edf2c4870bbf 165
dmwahl 4:edf2c4870bbf 166 bool ready; // signal whether or not an operation is in progress
dmwahl 0:9e74b14299fd 167 };
dmwahl 0:9e74b14299fd 168
dmwahl 0:9e74b14299fd 169 #endif