Mbed library for SPS30 i2c communication (Configured to be interfaced with TresidderOS) Inherits members and methods from SensorDriver class

Dependents:   SPS30_TEST

Committer:
ziqiyap
Date:
Thu Mar 28 01:14:03 2019 +0000
Revision:
10:228c926a2416
Parent:
9:a5fe43e183e2
added test cases; added timeout counter for data not ready

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ziqiyap 0:9221dac25d3b 1 #include "mbed.h"
ziqiyap 0:9221dac25d3b 2 #include "sps30.h"
ziqiyap 0:9221dac25d3b 3
ziqiyap 0:9221dac25d3b 4 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 5 // Constructor
ziqiyap 0:9221dac25d3b 6
ziqiyap 8:f6b216228067 7 Sps30::Sps30(PinName sda, PinName scl, int i2c_frequency) : _i2c(sda, scl) {
ziqiyap 4:7558ddc3c7d6 8 _i2c.frequency(i2c_frequency);
ziqiyap 9:a5fe43e183e2 9
ziqiyap 9:a5fe43e183e2 10 sensor_data_name.push_back("PM1.0 Mass");
ziqiyap 9:a5fe43e183e2 11 sensor_data_name.push_back("PM2.5 Mass");
ziqiyap 9:a5fe43e183e2 12 sensor_data_name.push_back("PM4.0 Mass");
ziqiyap 9:a5fe43e183e2 13 sensor_data_name.push_back("PM10.0 Mass");
ziqiyap 9:a5fe43e183e2 14 sensor_data_name.push_back("PM0.5 Num");
ziqiyap 9:a5fe43e183e2 15 sensor_data_name.push_back("PM1.0 Num");
ziqiyap 9:a5fe43e183e2 16 sensor_data_name.push_back("PM2.5 Num");
ziqiyap 9:a5fe43e183e2 17 sensor_data_name.push_back("PM4.0 Num");
ziqiyap 9:a5fe43e183e2 18 sensor_data_name.push_back("PM10.0 Num");
ziqiyap 9:a5fe43e183e2 19 sensor_data_name.push_back("Typical Particle Size");
ziqiyap 0:9221dac25d3b 20 }
ziqiyap 0:9221dac25d3b 21
ziqiyap 0:9221dac25d3b 22 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 23 // Destructor
ziqiyap 0:9221dac25d3b 24
ziqiyap 8:f6b216228067 25 Sps30::~Sps30() {
ziqiyap 0:9221dac25d3b 26 }
ziqiyap 0:9221dac25d3b 27
ziqiyap 0:9221dac25d3b 28 //-----------------------------------------------------------------------------
ziqiyap 2:549bee9a4cd0 29 // start auto-measurement
ziqiyap 0:9221dac25d3b 30 //
ziqiyap 0:9221dac25d3b 31
ziqiyap 8:f6b216228067 32 uint8_t Sps30::StartMeasurement()
ziqiyap 0:9221dac25d3b 33 {
ziqiyap 4:7558ddc3c7d6 34 i2cbuff[0] = SPS30_CMMD_STRT_MEAS >> 8;
ziqiyap 4:7558ddc3c7d6 35 i2cbuff[1] = SPS30_CMMD_STRT_MEAS & 255;
ziqiyap 4:7558ddc3c7d6 36 i2cbuff[2] = SPS30_STRT_MEAS_WRITE_DATA >> 8;
ziqiyap 4:7558ddc3c7d6 37 i2cbuff[3] = SPS30_STRT_MEAS_WRITE_DATA & 255;
ziqiyap 8:f6b216228067 38 i2cbuff[4] = Sps30::CalcCrc2b(SPS30_STRT_MEAS_WRITE_DATA);
ziqiyap 4:7558ddc3c7d6 39 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 5, false);
ziqiyap 6:83ed80f27fff 40 if(res) return SPSNOACKERROR;
ziqiyap 6:83ed80f27fff 41 return SPSNOERROR;
ziqiyap 0:9221dac25d3b 42 }
ziqiyap 0:9221dac25d3b 43
ziqiyap 0:9221dac25d3b 44 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 45 // Stop auto-measurement
ziqiyap 0:9221dac25d3b 46
ziqiyap 8:f6b216228067 47 uint8_t Sps30::StopMeasurement()
ziqiyap 0:9221dac25d3b 48 {
ziqiyap 4:7558ddc3c7d6 49 i2cbuff[0] = SPS30_CMMD_STOP_MEAS >> 8;
ziqiyap 4:7558ddc3c7d6 50 i2cbuff[1] = SPS30_CMMD_STOP_MEAS & 255;
ziqiyap 4:7558ddc3c7d6 51 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 52 if(res) return SPSNOACKERROR;
ziqiyap 6:83ed80f27fff 53 return SPSNOERROR;
ziqiyap 0:9221dac25d3b 54 }
ziqiyap 0:9221dac25d3b 55
ziqiyap 0:9221dac25d3b 56 //-----------------------------------------------------------------------------
ziqiyap 9:a5fe43e183e2 57 // Get Sps30 serial number
ziqiyap 9:a5fe43e183e2 58
ziqiyap 9:a5fe43e183e2 59 int Sps30::GetSerialNumber()
ziqiyap 9:a5fe43e183e2 60 {
ziqiyap 9:a5fe43e183e2 61 i2cbuff[0] = SPS30_CMMD_READ_SERIALNBR >> 8;
ziqiyap 9:a5fe43e183e2 62 i2cbuff[1] = SPS30_CMMD_READ_SERIALNBR & 255;
ziqiyap 9:a5fe43e183e2 63 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 9:a5fe43e183e2 64 if(res) return SPSNOACKERROR;
ziqiyap 9:a5fe43e183e2 65
ziqiyap 9:a5fe43e183e2 66 int i = 0;
ziqiyap 9:a5fe43e183e2 67 for(i = 0; i < sizeof(sn); i++) sn[i] = 0;
ziqiyap 9:a5fe43e183e2 68 for(i = 0; i < sizeof(i2cbuff); i++) i2cbuff[i] = 0;
ziqiyap 9:a5fe43e183e2 69
ziqiyap 9:a5fe43e183e2 70 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, SPS30_SN_SIZE, false);
ziqiyap 9:a5fe43e183e2 71 int t = 0;
ziqiyap 9:a5fe43e183e2 72 for(i = 0; i < SPS30_SN_SIZE; i +=3)
ziqiyap 9:a5fe43e183e2 73 {
ziqiyap 9:a5fe43e183e2 74 uint16_t stat = (i2cbuff[i] << 8) | i2cbuff[i + 1];
ziqiyap 9:a5fe43e183e2 75 sn[i - t] = stat >> 8;
ziqiyap 9:a5fe43e183e2 76 sn[i - t + 1] = stat & 255;
ziqiyap 9:a5fe43e183e2 77 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[i + 2]);
ziqiyap 9:a5fe43e183e2 78 t++;
ziqiyap 9:a5fe43e183e2 79 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 9:a5fe43e183e2 80 if(stat == 0) break;
ziqiyap 9:a5fe43e183e2 81 }
ziqiyap 9:a5fe43e183e2 82
ziqiyap 9:a5fe43e183e2 83 return SPSNOERROR;
ziqiyap 9:a5fe43e183e2 84 }
ziqiyap 9:a5fe43e183e2 85
ziqiyap 9:a5fe43e183e2 86 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 87 // Get ready status value
ziqiyap 0:9221dac25d3b 88
ziqiyap 8:f6b216228067 89 uint8_t Sps30::GetReadyStatus()
ziqiyap 0:9221dac25d3b 90 {
ziqiyap 4:7558ddc3c7d6 91 i2cbuff[0] = SPS30_CMMD_GET_READY_STAT >> 8;
ziqiyap 4:7558ddc3c7d6 92 i2cbuff[1] = SPS30_CMMD_GET_READY_STAT & 255;
ziqiyap 4:7558ddc3c7d6 93 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 94 if(res) return SPSNOACKERROR;
ziqiyap 0:9221dac25d3b 95
ziqiyap 4:7558ddc3c7d6 96 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 3, false);
ziqiyap 4:7558ddc3c7d6 97 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1];
ziqiyap 8:f6b216228067 98 sps_ready = stat;
ziqiyap 8:f6b216228067 99 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]);
ziqiyap 0:9221dac25d3b 100
ziqiyap 6:83ed80f27fff 101 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 6:83ed80f27fff 102 return SPSNOERROR;
ziqiyap 0:9221dac25d3b 103 }
ziqiyap 0:9221dac25d3b 104
ziqiyap 0:9221dac25d3b 105 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 106 // Get all the measurement values, stick them into the array
ziqiyap 0:9221dac25d3b 107
ziqiyap 8:f6b216228067 108 uint8_t Sps30::ReadMeasurement()
ziqiyap 0:9221dac25d3b 109 {
ziqiyap 4:7558ddc3c7d6 110 i2cbuff[0] = SPS30_CMMD_READ_MEAS >> 8;
ziqiyap 4:7558ddc3c7d6 111 i2cbuff[1] = SPS30_CMMD_READ_MEAS & 255;
ziqiyap 4:7558ddc3c7d6 112 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 113 if(res) return SPSNOACKERROR;
ziqiyap 0:9221dac25d3b 114
ziqiyap 4:7558ddc3c7d6 115 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 60, false);
ziqiyap 0:9221dac25d3b 116
ziqiyap 4:7558ddc3c7d6 117 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1];
ziqiyap 0:9221dac25d3b 118 mass_1p0_m = stat;
ziqiyap 8:f6b216228067 119 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]);
ziqiyap 6:83ed80f27fff 120 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 121
ziqiyap 4:7558ddc3c7d6 122 stat = (i2cbuff[3] << 8) | i2cbuff[4];
ziqiyap 0:9221dac25d3b 123 mass_1p0_l = stat;
ziqiyap 8:f6b216228067 124 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]);
ziqiyap 6:83ed80f27fff 125 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 126
ziqiyap 0:9221dac25d3b 127
ziqiyap 0:9221dac25d3b 128
ziqiyap 4:7558ddc3c7d6 129 stat = (i2cbuff[6] << 8) | i2cbuff[7];
ziqiyap 0:9221dac25d3b 130 mass_2p5_m = stat;
ziqiyap 8:f6b216228067 131 dat = Sps30::CheckCrc2b(stat, i2cbuff[8]);
ziqiyap 6:83ed80f27fff 132 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 133
ziqiyap 4:7558ddc3c7d6 134 stat = (i2cbuff[9] << 8) | i2cbuff[10];
ziqiyap 0:9221dac25d3b 135 mass_2p5_l = stat;
ziqiyap 8:f6b216228067 136 dat = Sps30::CheckCrc2b(stat, i2cbuff[11]);
ziqiyap 6:83ed80f27fff 137 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 138
ziqiyap 0:9221dac25d3b 139
ziqiyap 0:9221dac25d3b 140
ziqiyap 4:7558ddc3c7d6 141 stat = (i2cbuff[12] << 8) | i2cbuff[13];
ziqiyap 0:9221dac25d3b 142 mass_4p0_m = stat;
ziqiyap 8:f6b216228067 143 dat = Sps30::CheckCrc2b(stat, i2cbuff[14]);
ziqiyap 6:83ed80f27fff 144 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 145
ziqiyap 4:7558ddc3c7d6 146 stat = (i2cbuff[15] << 8) | i2cbuff[16];
ziqiyap 0:9221dac25d3b 147 mass_4p0_l = stat;
ziqiyap 8:f6b216228067 148 dat = Sps30::CheckCrc2b(stat, i2cbuff[17]);
ziqiyap 6:83ed80f27fff 149 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 150
ziqiyap 0:9221dac25d3b 151
ziqiyap 0:9221dac25d3b 152
ziqiyap 4:7558ddc3c7d6 153 stat = (i2cbuff[18] << 8) | i2cbuff[19];
ziqiyap 0:9221dac25d3b 154 mass_10p0_m = stat;
ziqiyap 8:f6b216228067 155 dat = Sps30::CheckCrc2b(stat, i2cbuff[20]);
ziqiyap 6:83ed80f27fff 156 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 157
ziqiyap 4:7558ddc3c7d6 158 stat = (i2cbuff[21] << 8) | i2cbuff[22];
ziqiyap 0:9221dac25d3b 159 mass_10p0_l = stat;
ziqiyap 8:f6b216228067 160 dat = Sps30::CheckCrc2b(stat, i2cbuff[23]);
ziqiyap 6:83ed80f27fff 161 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 162
ziqiyap 0:9221dac25d3b 163
ziqiyap 0:9221dac25d3b 164
ziqiyap 4:7558ddc3c7d6 165 stat = (i2cbuff[24] << 8) | i2cbuff[25];
ziqiyap 0:9221dac25d3b 166 num_0p5_m = stat;
ziqiyap 8:f6b216228067 167 dat = Sps30::CheckCrc2b(stat, i2cbuff[26]);
ziqiyap 6:83ed80f27fff 168 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 169
ziqiyap 4:7558ddc3c7d6 170 stat = (i2cbuff[27] << 8) | i2cbuff[28];
ziqiyap 0:9221dac25d3b 171 num_0p5_l = stat;
ziqiyap 8:f6b216228067 172 dat = Sps30::CheckCrc2b(stat, i2cbuff[29]);
ziqiyap 6:83ed80f27fff 173 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 174
ziqiyap 0:9221dac25d3b 175
ziqiyap 4:7558ddc3c7d6 176 stat = (i2cbuff[30] << 8) | i2cbuff[31];
ziqiyap 0:9221dac25d3b 177 num_1p0_m = stat;
ziqiyap 8:f6b216228067 178 dat = Sps30::CheckCrc2b(stat, i2cbuff[32]);
ziqiyap 6:83ed80f27fff 179 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 180
ziqiyap 4:7558ddc3c7d6 181 stat = (i2cbuff[33] << 8) | i2cbuff[34];
ziqiyap 0:9221dac25d3b 182 num_1p0_l = stat;
ziqiyap 8:f6b216228067 183 dat = Sps30::CheckCrc2b(stat, i2cbuff[35]);
ziqiyap 6:83ed80f27fff 184 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 185
ziqiyap 0:9221dac25d3b 186
ziqiyap 0:9221dac25d3b 187
ziqiyap 4:7558ddc3c7d6 188 stat = (i2cbuff[36] << 8) | i2cbuff[37];
ziqiyap 0:9221dac25d3b 189 num_2p5_m = stat;
ziqiyap 8:f6b216228067 190 dat = Sps30::CheckCrc2b(stat, i2cbuff[38]);
ziqiyap 6:83ed80f27fff 191 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 192
ziqiyap 4:7558ddc3c7d6 193 stat = (i2cbuff[39] << 8) | i2cbuff[40];
ziqiyap 0:9221dac25d3b 194 num_2p5_l = stat;
ziqiyap 8:f6b216228067 195 dat = Sps30::CheckCrc2b(stat, i2cbuff[41]);
ziqiyap 6:83ed80f27fff 196 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 197
ziqiyap 0:9221dac25d3b 198
ziqiyap 0:9221dac25d3b 199
ziqiyap 4:7558ddc3c7d6 200 stat = (i2cbuff[42] << 8) | i2cbuff[43];
ziqiyap 0:9221dac25d3b 201 num_4p0_m = stat;
ziqiyap 8:f6b216228067 202 dat = Sps30::CheckCrc2b(stat, i2cbuff[44]);
ziqiyap 6:83ed80f27fff 203 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 204
ziqiyap 4:7558ddc3c7d6 205 stat = (i2cbuff[45] << 8) | i2cbuff[46];
ziqiyap 0:9221dac25d3b 206 num_4p0_l = stat;
ziqiyap 8:f6b216228067 207 dat = Sps30::CheckCrc2b(stat, i2cbuff[47]);
ziqiyap 6:83ed80f27fff 208 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 209
ziqiyap 0:9221dac25d3b 210
ziqiyap 4:7558ddc3c7d6 211 stat = (i2cbuff[48] << 8) | i2cbuff[49];
ziqiyap 0:9221dac25d3b 212 num_10p0_m = stat;
ziqiyap 8:f6b216228067 213 dat = Sps30::CheckCrc2b(stat, i2cbuff[50]);
ziqiyap 6:83ed80f27fff 214 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 215
ziqiyap 4:7558ddc3c7d6 216 stat = (i2cbuff[51] << 8) | i2cbuff[52];
ziqiyap 0:9221dac25d3b 217 num_10p0_l = stat;
ziqiyap 8:f6b216228067 218 dat = Sps30::CheckCrc2b(stat, i2cbuff[53]);
ziqiyap 6:83ed80f27fff 219 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 220
ziqiyap 0:9221dac25d3b 221
ziqiyap 4:7558ddc3c7d6 222 stat = (i2cbuff[54] << 8) | i2cbuff[55];
ziqiyap 0:9221dac25d3b 223 typ_pm_size_m = stat;
ziqiyap 8:f6b216228067 224 dat = Sps30::CheckCrc2b(stat, i2cbuff[56]);
ziqiyap 6:83ed80f27fff 225 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 226
ziqiyap 4:7558ddc3c7d6 227 stat = (i2cbuff[57] << 8) | i2cbuff[58];
ziqiyap 0:9221dac25d3b 228 typ_pm_size_l = stat;
ziqiyap 8:f6b216228067 229 dat = Sps30::CheckCrc2b(stat, i2cbuff[59]);
ziqiyap 6:83ed80f27fff 230 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 0:9221dac25d3b 231
ziqiyap 0:9221dac25d3b 232 mass_1p0_i = (mass_1p0_m << 16) | mass_1p0_l;
ziqiyap 0:9221dac25d3b 233 mass_2p5_i = (mass_2p5_m << 16) | mass_2p5_l;
ziqiyap 0:9221dac25d3b 234 mass_4p0_i = (mass_4p0_m << 16) | mass_4p0_l;
ziqiyap 0:9221dac25d3b 235 mass_10p0_i = (mass_10p0_m << 16) | mass_10p0_l;
ziqiyap 0:9221dac25d3b 236
ziqiyap 0:9221dac25d3b 237 num_0p5_i = (num_0p5_m << 16) | num_0p5_l;
ziqiyap 0:9221dac25d3b 238 num_1p0_i = (num_1p0_m << 16) | num_1p0_l;
ziqiyap 0:9221dac25d3b 239 num_2p5_i = (num_2p5_m << 16) | num_2p5_l;
ziqiyap 0:9221dac25d3b 240 num_4p0_i = (num_4p0_m << 16) | num_4p0_l;
ziqiyap 0:9221dac25d3b 241 num_10p0_i = (num_10p0_m << 16) | num_10p0_l;
ziqiyap 0:9221dac25d3b 242
ziqiyap 0:9221dac25d3b 243 typ_pm_size_i = (typ_pm_size_m << 16) | typ_pm_size_l;
ziqiyap 0:9221dac25d3b 244
ziqiyap 0:9221dac25d3b 245 mass_1p0_f = *(float*)&mass_1p0_i;
ziqiyap 0:9221dac25d3b 246 mass_2p5_f = *(float*)&mass_2p5_i;
ziqiyap 0:9221dac25d3b 247 mass_4p0_f = *(float*)&mass_4p0_i;
ziqiyap 0:9221dac25d3b 248 mass_10p0_f = *(float*)&mass_10p0_i;
ziqiyap 0:9221dac25d3b 249
ziqiyap 0:9221dac25d3b 250 num_0p5_f = *(float*)&num_0p5_i;
ziqiyap 0:9221dac25d3b 251 num_1p0_f = *(float*)&num_1p0_i;
ziqiyap 0:9221dac25d3b 252 num_2p5_f = *(float*)&num_2p5_i;
ziqiyap 0:9221dac25d3b 253 num_4p0_f = *(float*)&num_4p0_i;
ziqiyap 0:9221dac25d3b 254 num_10p0_f = *(float*)&num_10p0_i;
ziqiyap 0:9221dac25d3b 255
ziqiyap 0:9221dac25d3b 256 typ_pm_size_f = *(float*)&typ_pm_size_i;
ziqiyap 0:9221dac25d3b 257
ziqiyap 6:83ed80f27fff 258 return SPSNOERROR;
ziqiyap 0:9221dac25d3b 259 }
ziqiyap 0:9221dac25d3b 260
ziqiyap 0:9221dac25d3b 261 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 262 // Calculate the CRC of a 2 byte value using the SPS30 CRC polynomial
ziqiyap 0:9221dac25d3b 263
ziqiyap 8:f6b216228067 264 uint8_t Sps30::CalcCrc2b(uint16_t seed)
ziqiyap 0:9221dac25d3b 265 {
ziqiyap 0:9221dac25d3b 266 uint8_t bit; // bit mask
ziqiyap 0:9221dac25d3b 267 uint8_t crc = SPS30_CRC_INIT; // calculated checksum
ziqiyap 0:9221dac25d3b 268
ziqiyap 0:9221dac25d3b 269 // calculates 8-Bit checksum with given polynomial
ziqiyap 0:9221dac25d3b 270
ziqiyap 0:9221dac25d3b 271 crc ^= (seed >> 8) & 255;
ziqiyap 0:9221dac25d3b 272 for(bit = 8; bit > 0; --bit)
ziqiyap 0:9221dac25d3b 273 {
ziqiyap 0:9221dac25d3b 274 if(crc & 0x80) crc = (crc << 1) ^ SPS30_POLYNOMIAL;
ziqiyap 0:9221dac25d3b 275 else crc = (crc << 1);
ziqiyap 0:9221dac25d3b 276 }
ziqiyap 0:9221dac25d3b 277
ziqiyap 0:9221dac25d3b 278 crc ^= seed & 255;
ziqiyap 0:9221dac25d3b 279 for(bit = 8; bit > 0; --bit)
ziqiyap 0:9221dac25d3b 280 {
ziqiyap 0:9221dac25d3b 281 if(crc & 0x80) crc = (crc << 1) ^ SPS30_POLYNOMIAL;
ziqiyap 0:9221dac25d3b 282 else crc = (crc << 1);
ziqiyap 0:9221dac25d3b 283 }
ziqiyap 0:9221dac25d3b 284
ziqiyap 0:9221dac25d3b 285 return crc;
ziqiyap 0:9221dac25d3b 286 }
ziqiyap 0:9221dac25d3b 287
ziqiyap 0:9221dac25d3b 288 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 289 // Compare the CRC values
ziqiyap 0:9221dac25d3b 290
ziqiyap 8:f6b216228067 291 uint8_t Sps30::CheckCrc2b(uint16_t seed, uint8_t crc_in)
ziqiyap 0:9221dac25d3b 292 {
ziqiyap 8:f6b216228067 293 uint8_t crc_calc = Sps30::CalcCrc2b(seed);
ziqiyap 6:83ed80f27fff 294 if(crc_calc != crc_in) return SPSCRCERROR;
ziqiyap 6:83ed80f27fff 295 return SPSNOERROR;
ziqiyap 0:9221dac25d3b 296 }
ziqiyap 0:9221dac25d3b 297
ziqiyap 0:9221dac25d3b 298 //-----------------------------------------------------------------------------
ziqiyap 2:549bee9a4cd0 299 // Read Auto Cleaning Interval on the SPS30
ziqiyap 2:549bee9a4cd0 300
ziqiyap 8:f6b216228067 301 uint8_t Sps30::ReadAutoCleanInterval()
ziqiyap 2:549bee9a4cd0 302 {
ziqiyap 4:7558ddc3c7d6 303 i2cbuff[0] = SPS30_CMMD_AUTO_CLEAN_INTV >> 8;
ziqiyap 4:7558ddc3c7d6 304 i2cbuff[1] = SPS30_CMMD_AUTO_CLEAN_INTV & 255;
ziqiyap 2:549bee9a4cd0 305
ziqiyap 4:7558ddc3c7d6 306 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 307 if(res) return SPSNOACKERROR;
ziqiyap 2:549bee9a4cd0 308
ziqiyap 4:7558ddc3c7d6 309 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 6, false);
ziqiyap 2:549bee9a4cd0 310
ziqiyap 4:7558ddc3c7d6 311 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1];
ziqiyap 2:549bee9a4cd0 312 clean_interval_m = stat;
ziqiyap 8:f6b216228067 313 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]);
ziqiyap 6:83ed80f27fff 314 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 2:549bee9a4cd0 315
ziqiyap 4:7558ddc3c7d6 316 stat = (i2cbuff[3] << 8) | i2cbuff[4];
ziqiyap 2:549bee9a4cd0 317 clean_interval_l = stat;
ziqiyap 8:f6b216228067 318 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]);
ziqiyap 6:83ed80f27fff 319 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 2:549bee9a4cd0 320
ziqiyap 2:549bee9a4cd0 321 clean_interval_i = (clean_interval_m << 16) | clean_interval_l;
ziqiyap 2:549bee9a4cd0 322
ziqiyap 6:83ed80f27fff 323 return SPSNOERROR;
ziqiyap 2:549bee9a4cd0 324 }
ziqiyap 2:549bee9a4cd0 325
ziqiyap 2:549bee9a4cd0 326 //-----------------------------------------------------------------------------
ziqiyap 2:549bee9a4cd0 327 // Set Auto Cleaning Interval on the SPS30
ziqiyap 2:549bee9a4cd0 328
ziqiyap 8:f6b216228067 329 uint8_t Sps30::SetAutoCleanInterval(uint32_t set_interval)
ziqiyap 2:549bee9a4cd0 330 {
ziqiyap 2:549bee9a4cd0 331 uint16_t set_interval_m = set_interval >> 16;
ziqiyap 2:549bee9a4cd0 332 uint16_t set_interval_l = set_interval & 65535;
ziqiyap 2:549bee9a4cd0 333
ziqiyap 4:7558ddc3c7d6 334 i2cbuff[0] = SPS30_CMMD_AUTO_CLEAN_INTV >> 8;
ziqiyap 4:7558ddc3c7d6 335 i2cbuff[1] = SPS30_CMMD_AUTO_CLEAN_INTV & 255;
ziqiyap 2:549bee9a4cd0 336
ziqiyap 4:7558ddc3c7d6 337 i2cbuff[2] = set_interval_m >> 8;
ziqiyap 4:7558ddc3c7d6 338 i2cbuff[3] = set_interval_m & 255;
ziqiyap 8:f6b216228067 339 i2cbuff[4] = Sps30::CalcCrc2b(set_interval_m);
ziqiyap 2:549bee9a4cd0 340
ziqiyap 4:7558ddc3c7d6 341 i2cbuff[5] = set_interval_l >> 8;
ziqiyap 4:7558ddc3c7d6 342 i2cbuff[6] = set_interval_l & 255;
ziqiyap 8:f6b216228067 343 i2cbuff[7] = Sps30::CalcCrc2b(set_interval_l);
ziqiyap 2:549bee9a4cd0 344
ziqiyap 4:7558ddc3c7d6 345 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 8, false);
ziqiyap 6:83ed80f27fff 346 if(res) return SPSNOACKERROR;
ziqiyap 2:549bee9a4cd0 347
ziqiyap 4:7558ddc3c7d6 348 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 6, false);
ziqiyap 2:549bee9a4cd0 349
ziqiyap 4:7558ddc3c7d6 350 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1];
ziqiyap 2:549bee9a4cd0 351 clean_interval_m = stat;
ziqiyap 8:f6b216228067 352 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]);
ziqiyap 6:83ed80f27fff 353 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 2:549bee9a4cd0 354
ziqiyap 4:7558ddc3c7d6 355 stat = (i2cbuff[3] << 8) | i2cbuff[4];
ziqiyap 2:549bee9a4cd0 356 clean_interval_l = stat;
ziqiyap 8:f6b216228067 357 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]);
ziqiyap 6:83ed80f27fff 358 if(dat == SPSCRCERROR) return SPSCRCERROR;
ziqiyap 2:549bee9a4cd0 359
ziqiyap 2:549bee9a4cd0 360 clean_interval_i = (clean_interval_m << 16) | clean_interval_l;
ziqiyap 2:549bee9a4cd0 361
ziqiyap 6:83ed80f27fff 362 return SPSNOERROR;
ziqiyap 2:549bee9a4cd0 363 }
ziqiyap 2:549bee9a4cd0 364
ziqiyap 2:549bee9a4cd0 365 //-----------------------------------------------------------------------------
ziqiyap 2:549bee9a4cd0 366 // Perform manual fan cleaning
ziqiyap 2:549bee9a4cd0 367
ziqiyap 8:f6b216228067 368 uint8_t Sps30::StartFanClean()
ziqiyap 2:549bee9a4cd0 369 {
ziqiyap 4:7558ddc3c7d6 370 i2cbuff[0] = SPS30_CMMD_START_FAN_CLEAN >> 8;
ziqiyap 4:7558ddc3c7d6 371 i2cbuff[1] = SPS30_CMMD_START_FAN_CLEAN & 255;
ziqiyap 4:7558ddc3c7d6 372 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 373 if(res) return SPSNOACKERROR;
ziqiyap 6:83ed80f27fff 374 return SPSNOERROR;
ziqiyap 2:549bee9a4cd0 375 }
ziqiyap 2:549bee9a4cd0 376
ziqiyap 2:549bee9a4cd0 377 //-----------------------------------------------------------------------------
ziqiyap 0:9221dac25d3b 378 // Perform a soft reset on the SPS30
ziqiyap 0:9221dac25d3b 379
ziqiyap 8:f6b216228067 380 uint8_t Sps30::SoftReset()
ziqiyap 0:9221dac25d3b 381 {
ziqiyap 4:7558ddc3c7d6 382 i2cbuff[0] = SPS30_CMMD_SOFT_RESET >> 8;
ziqiyap 4:7558ddc3c7d6 383 i2cbuff[1] = SPS30_CMMD_SOFT_RESET & 255;
ziqiyap 4:7558ddc3c7d6 384 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false);
ziqiyap 6:83ed80f27fff 385 if(res) return SPSNOACKERROR;
ziqiyap 6:83ed80f27fff 386 return SPSNOERROR;
ziqiyap 8:f6b216228067 387 }
ziqiyap 8:f6b216228067 388
ziqiyap 9:a5fe43e183e2 389 //-----------------------------------------------------------------------------
ziqiyap 9:a5fe43e183e2 390 // Fill up the sensor data vector to be read in Sensor Thread
ziqiyap 9:a5fe43e183e2 391
ziqiyap 9:a5fe43e183e2 392 void Sps30::GetDataArray()
ziqiyap 9:a5fe43e183e2 393 {
ziqiyap 9:a5fe43e183e2 394 sensor_float_data.clear();
ziqiyap 9:a5fe43e183e2 395
ziqiyap 9:a5fe43e183e2 396 sensor_float_data.push_back(mass_1p0_f);
ziqiyap 9:a5fe43e183e2 397 sensor_float_data.push_back(mass_2p5_f);
ziqiyap 9:a5fe43e183e2 398 sensor_float_data.push_back(mass_4p0_f);
ziqiyap 9:a5fe43e183e2 399 sensor_float_data.push_back(mass_10p0_f);
ziqiyap 9:a5fe43e183e2 400
ziqiyap 9:a5fe43e183e2 401 sensor_float_data.push_back(num_0p5_f);
ziqiyap 9:a5fe43e183e2 402 sensor_float_data.push_back(num_1p0_f);
ziqiyap 9:a5fe43e183e2 403 sensor_float_data.push_back(num_2p5_f);
ziqiyap 9:a5fe43e183e2 404 sensor_float_data.push_back(num_4p0_f);
ziqiyap 9:a5fe43e183e2 405 sensor_float_data.push_back(num_10p0_f);
ziqiyap 9:a5fe43e183e2 406
ziqiyap 9:a5fe43e183e2 407 sensor_float_data.push_back(typ_pm_size_f);
ziqiyap 9:a5fe43e183e2 408
ziqiyap 9:a5fe43e183e2 409 int i = 0;
ziqiyap 9:a5fe43e183e2 410 for (i = 0; i < sensor_float_data.size(); i++)
ziqiyap 9:a5fe43e183e2 411 {
ziqiyap 9:a5fe43e183e2 412 std::string sensor_string_data = ConvertDataToString(sensor_float_data[i]);
ziqiyap 9:a5fe43e183e2 413 sensor_data.push_back( make_pair(sensor_data_name[i],sensor_string_data) );
ziqiyap 9:a5fe43e183e2 414
ziqiyap 9:a5fe43e183e2 415 int val_data;
ziqiyap 9:a5fe43e183e2 416 if (i < 4)
ziqiyap 9:a5fe43e183e2 417 {
ziqiyap 10:228c926a2416 418 // sensor_float_data[i] = 99999.00; // test use case 3c; expected output: EmTrace for sensor data out-of-range with data value
ziqiyap 9:a5fe43e183e2 419 val_data = ValidateData(sensor_float_data[i], MASS_MIN, MASS_MAX);
ziqiyap 9:a5fe43e183e2 420 }
ziqiyap 9:a5fe43e183e2 421 else if (i < 9)
ziqiyap 9:a5fe43e183e2 422 {
ziqiyap 10:228c926a2416 423 // sensor_float_data[i] = 99999.00; // test use case 3c; expected output: EmTrace for sensor data out-of-range with data value
ziqiyap 9:a5fe43e183e2 424 val_data = ValidateData(sensor_float_data[i], NUM_MIN, NUM_MAX);
ziqiyap 9:a5fe43e183e2 425 }
ziqiyap 9:a5fe43e183e2 426
ziqiyap 9:a5fe43e183e2 427 if (val_data == SENSOR_DATAOOR)
ziqiyap 9:a5fe43e183e2 428 {
ziqiyap 9:a5fe43e183e2 429 std::string oor_string = sensor_data_name[i] + " is out-of-range: " + sensor_string_data;
ziqiyap 9:a5fe43e183e2 430 SendSensorEmTrace(SENSOR_DATAOOR, oor_string);
ziqiyap 9:a5fe43e183e2 431 }
ziqiyap 9:a5fe43e183e2 432 }
ziqiyap 9:a5fe43e183e2 433 return;
ziqiyap 9:a5fe43e183e2 434 }
ziqiyap 9:a5fe43e183e2 435
ziqiyap 8:f6b216228067 436 /************************** PUBLIC METHODS **********************************/
ziqiyap 8:f6b216228067 437
ziqiyap 8:f6b216228067 438 //-----------------------------------------------------------------------------
ziqiyap 8:f6b216228067 439 // Initialise SPS30
ziqiyap 8:f6b216228067 440
ziqiyap 9:a5fe43e183e2 441 void Sps30::InitSensor()
ziqiyap 9:a5fe43e183e2 442 {
ziqiyap 8:f6b216228067 443 uint8_t dat = Sps30::GetSerialNumber();
ziqiyap 9:a5fe43e183e2 444 if (dat == SPSNOACKERROR)
ziqiyap 9:a5fe43e183e2 445 {
ziqiyap 9:a5fe43e183e2 446 SendSensorEmTrace(SENSOR_DCN);
ziqiyap 10:228c926a2416 447 sps_status = 0;
ziqiyap 9:a5fe43e183e2 448 }
ziqiyap 9:a5fe43e183e2 449
ziqiyap 9:a5fe43e183e2 450 dat = Sps30::StartMeasurement();
ziqiyap 9:a5fe43e183e2 451 if (dat == SPSNOACKERROR)
ziqiyap 9:a5fe43e183e2 452 {
ziqiyap 9:a5fe43e183e2 453 SendSensorEmTrace(SENSOR_DCN);
ziqiyap 10:228c926a2416 454 sps_status = 0;
ziqiyap 9:a5fe43e183e2 455 }
ziqiyap 9:a5fe43e183e2 456
ziqiyap 9:a5fe43e183e2 457 SendSensorEmTrace(SENSOR_CN);
ziqiyap 9:a5fe43e183e2 458 sensor_serial = ConvertSerialNumber(sn);
ziqiyap 10:228c926a2416 459 sps_status = 1;
ziqiyap 10:228c926a2416 460 t_count = 0;
ziqiyap 8:f6b216228067 461
ziqiyap 9:a5fe43e183e2 462 return;
ziqiyap 8:f6b216228067 463 }
ziqiyap 8:f6b216228067 464
ziqiyap 8:f6b216228067 465 //-----------------------------------------------------------------------------
ziqiyap 8:f6b216228067 466 // Poll SPS30
ziqiyap 8:f6b216228067 467
ziqiyap 9:a5fe43e183e2 468 int Sps30::PollSensor()
ziqiyap 8:f6b216228067 469 {
ziqiyap 9:a5fe43e183e2 470 sensor_data.clear();
ziqiyap 8:f6b216228067 471 uint8_t dat = Sps30::GetReadyStatus();
ziqiyap 9:a5fe43e183e2 472 if (dat == SPSNOACKERROR)
ziqiyap 9:a5fe43e183e2 473 {
ziqiyap 10:228c926a2416 474 if (sps_status == 1) SendSensorEmTrace(SENSOR_DCN);
ziqiyap 10:228c926a2416 475 sps_status = 0;
ziqiyap 9:a5fe43e183e2 476 return SENSOR_DCN;
ziqiyap 9:a5fe43e183e2 477 }
ziqiyap 8:f6b216228067 478
ziqiyap 10:228c926a2416 479 if (sps_status == 0)
ziqiyap 10:228c926a2416 480 {
ziqiyap 10:228c926a2416 481 Sps30::InitSensor(); // If was disconnected, reinitialise
ziqiyap 10:228c926a2416 482 Sps30::GetReadyStatus();
ziqiyap 10:228c926a2416 483 }
ziqiyap 10:228c926a2416 484 // sps_ready = 0; // test use case 3b; expeced output: EMTrace for sensor data not ready
ziqiyap 8:f6b216228067 485 if (sps_ready == SPSISREADY)
ziqiyap 8:f6b216228067 486 {
ziqiyap 8:f6b216228067 487 uint8_t crcc = Sps30::ReadMeasurement();
ziqiyap 10:228c926a2416 488 // crcc = SPSCRCERROR; // test use case 3b; expeced output: EMTrace for sensor data not ready
ziqiyap 8:f6b216228067 489 if (crcc == SPSNOERROR)
ziqiyap 8:f6b216228067 490 {
ziqiyap 9:a5fe43e183e2 491 Sps30::GetDataArray();
ziqiyap 9:a5fe43e183e2 492 return SENSOR_DATAOK;
ziqiyap 8:f6b216228067 493 }
ziqiyap 8:f6b216228067 494 else if (crcc == SPSNOACKERROR)
ziqiyap 8:f6b216228067 495 {
ziqiyap 9:a5fe43e183e2 496 SendSensorEmTrace(SENSOR_DCN);
ziqiyap 10:228c926a2416 497 sps_status = 0;
ziqiyap 9:a5fe43e183e2 498 return SENSOR_DCN;
ziqiyap 8:f6b216228067 499 }
ziqiyap 8:f6b216228067 500 else
ziqiyap 8:f6b216228067 501 {
ziqiyap 9:a5fe43e183e2 502 SendSensorEmTrace(SENSOR_DATAERR);
ziqiyap 9:a5fe43e183e2 503 return SENSOR_DATAERR;
ziqiyap 8:f6b216228067 504 }
ziqiyap 8:f6b216228067 505 }
ziqiyap 8:f6b216228067 506 else
ziqiyap 10:228c926a2416 507 {
ziqiyap 10:228c926a2416 508 if (t_count == TIMEOUT_COUNT) // timeout counter for data not ready
ziqiyap 10:228c926a2416 509 {
ziqiyap 10:228c926a2416 510 SendSensorEmTrace(SENSOR_DATAERR);
ziqiyap 10:228c926a2416 511 Sps30::SoftReset();
ziqiyap 10:228c926a2416 512 t_count = 0;
ziqiyap 10:228c926a2416 513 }
ziqiyap 10:228c926a2416 514 t_count++;
ziqiyap 10:228c926a2416 515
ziqiyap 9:a5fe43e183e2 516 return SENSOR_DATAERR;
ziqiyap 8:f6b216228067 517 }
ziqiyap 8:f6b216228067 518 }