Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: IZU2021_SPS30 Hybrid_IZU2021_MISSION_v2 Hybrid_IZU2021_MISSION
sps30.cpp
00001 #include "mbed.h" 00002 #include "sps30.h" 00003 00004 //----------------------------------------------------------------------------- 00005 // Constructor 00006 00007 Sps30::Sps30(PinName sda, PinName scl, int i2c_frequency) : _i2c(sda, scl) { 00008 _i2c.frequency(i2c_frequency); 00009 } 00010 00011 //----------------------------------------------------------------------------- 00012 // Destructor 00013 00014 Sps30::~Sps30() { 00015 } 00016 00017 //----------------------------------------------------------------------------- 00018 // start auto-measurement 00019 // 00020 00021 uint8_t Sps30::StartMeasurement() 00022 { 00023 i2cbuff[0] = SPS30_CMMD_STRT_MEAS >> 8; 00024 i2cbuff[1] = SPS30_CMMD_STRT_MEAS & 255; 00025 i2cbuff[2] = SPS30_STRT_MEAS_WRITE_DATA >> 8; 00026 i2cbuff[3] = SPS30_STRT_MEAS_WRITE_DATA & 255; 00027 i2cbuff[4] = Sps30::CalcCrc2b(SPS30_STRT_MEAS_WRITE_DATA); 00028 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 5, false); 00029 if(res) return SPSNOACKERROR; 00030 return SPSNOERROR; 00031 } 00032 00033 //----------------------------------------------------------------------------- 00034 // Stop auto-measurement 00035 00036 uint8_t Sps30::StopMeasurement() 00037 { 00038 i2cbuff[0] = SPS30_CMMD_STOP_MEAS >> 8; 00039 i2cbuff[1] = SPS30_CMMD_STOP_MEAS & 255; 00040 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00041 if(res) return SPSNOACKERROR; 00042 return SPSNOERROR; 00043 } 00044 00045 //----------------------------------------------------------------------------- 00046 // Get ready status value 00047 00048 uint8_t Sps30::GetReadyStatus() 00049 { 00050 i2cbuff[0] = SPS30_CMMD_GET_READY_STAT >> 8; 00051 i2cbuff[1] = SPS30_CMMD_GET_READY_STAT & 255; 00052 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00053 if(res) return SPSNOACKERROR; 00054 00055 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 3, false); 00056 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1]; 00057 sps_ready = stat; 00058 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]); 00059 00060 if(dat == SPSCRCERROR) return SPSCRCERROR; 00061 return SPSNOERROR; 00062 } 00063 00064 //----------------------------------------------------------------------------- 00065 // Get all the measurement values, stick them into the array 00066 00067 uint8_t Sps30::ReadMeasurement() 00068 { 00069 i2cbuff[0] = SPS30_CMMD_READ_MEAS >> 8; 00070 i2cbuff[1] = SPS30_CMMD_READ_MEAS & 255; 00071 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00072 if(res) return SPSNOACKERROR; 00073 00074 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 60, false); 00075 00076 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1]; 00077 mass_1p0_m = stat; 00078 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]); 00079 if(dat == SPSCRCERROR) return SPSCRCERROR; 00080 00081 stat = (i2cbuff[3] << 8) | i2cbuff[4]; 00082 mass_1p0_l = stat; 00083 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]); 00084 if(dat == SPSCRCERROR) return SPSCRCERROR; 00085 00086 00087 00088 stat = (i2cbuff[6] << 8) | i2cbuff[7]; 00089 mass_2p5_m = stat; 00090 dat = Sps30::CheckCrc2b(stat, i2cbuff[8]); 00091 if(dat == SPSCRCERROR) return SPSCRCERROR; 00092 00093 stat = (i2cbuff[9] << 8) | i2cbuff[10]; 00094 mass_2p5_l = stat; 00095 dat = Sps30::CheckCrc2b(stat, i2cbuff[11]); 00096 if(dat == SPSCRCERROR) return SPSCRCERROR; 00097 00098 00099 00100 stat = (i2cbuff[12] << 8) | i2cbuff[13]; 00101 mass_4p0_m = stat; 00102 dat = Sps30::CheckCrc2b(stat, i2cbuff[14]); 00103 if(dat == SPSCRCERROR) return SPSCRCERROR; 00104 00105 stat = (i2cbuff[15] << 8) | i2cbuff[16]; 00106 mass_4p0_l = stat; 00107 dat = Sps30::CheckCrc2b(stat, i2cbuff[17]); 00108 if(dat == SPSCRCERROR) return SPSCRCERROR; 00109 00110 00111 00112 stat = (i2cbuff[18] << 8) | i2cbuff[19]; 00113 mass_10p0_m = stat; 00114 dat = Sps30::CheckCrc2b(stat, i2cbuff[20]); 00115 if(dat == SPSCRCERROR) return SPSCRCERROR; 00116 00117 stat = (i2cbuff[21] << 8) | i2cbuff[22]; 00118 mass_10p0_l = stat; 00119 dat = Sps30::CheckCrc2b(stat, i2cbuff[23]); 00120 if(dat == SPSCRCERROR) return SPSCRCERROR; 00121 00122 00123 00124 stat = (i2cbuff[24] << 8) | i2cbuff[25]; 00125 num_0p5_m = stat; 00126 dat = Sps30::CheckCrc2b(stat, i2cbuff[26]); 00127 if(dat == SPSCRCERROR) return SPSCRCERROR; 00128 00129 stat = (i2cbuff[27] << 8) | i2cbuff[28]; 00130 num_0p5_l = stat; 00131 dat = Sps30::CheckCrc2b(stat, i2cbuff[29]); 00132 if(dat == SPSCRCERROR) return SPSCRCERROR; 00133 00134 00135 stat = (i2cbuff[30] << 8) | i2cbuff[31]; 00136 num_1p0_m = stat; 00137 dat = Sps30::CheckCrc2b(stat, i2cbuff[32]); 00138 if(dat == SPSCRCERROR) return SPSCRCERROR; 00139 00140 stat = (i2cbuff[33] << 8) | i2cbuff[34]; 00141 num_1p0_l = stat; 00142 dat = Sps30::CheckCrc2b(stat, i2cbuff[35]); 00143 if(dat == SPSCRCERROR) return SPSCRCERROR; 00144 00145 00146 00147 stat = (i2cbuff[36] << 8) | i2cbuff[37]; 00148 num_2p5_m = stat; 00149 dat = Sps30::CheckCrc2b(stat, i2cbuff[38]); 00150 if(dat == SPSCRCERROR) return SPSCRCERROR; 00151 00152 stat = (i2cbuff[39] << 8) | i2cbuff[40]; 00153 num_2p5_l = stat; 00154 dat = Sps30::CheckCrc2b(stat, i2cbuff[41]); 00155 if(dat == SPSCRCERROR) return SPSCRCERROR; 00156 00157 00158 00159 stat = (i2cbuff[42] << 8) | i2cbuff[43]; 00160 num_4p0_m = stat; 00161 dat = Sps30::CheckCrc2b(stat, i2cbuff[44]); 00162 if(dat == SPSCRCERROR) return SPSCRCERROR; 00163 00164 stat = (i2cbuff[45] << 8) | i2cbuff[46]; 00165 num_4p0_l = stat; 00166 dat = Sps30::CheckCrc2b(stat, i2cbuff[47]); 00167 if(dat == SPSCRCERROR) return SPSCRCERROR; 00168 00169 00170 stat = (i2cbuff[48] << 8) | i2cbuff[49]; 00171 num_10p0_m = stat; 00172 dat = Sps30::CheckCrc2b(stat, i2cbuff[50]); 00173 if(dat == SPSCRCERROR) return SPSCRCERROR; 00174 00175 stat = (i2cbuff[51] << 8) | i2cbuff[52]; 00176 num_10p0_l = stat; 00177 dat = Sps30::CheckCrc2b(stat, i2cbuff[53]); 00178 if(dat == SPSCRCERROR) return SPSCRCERROR; 00179 00180 00181 stat = (i2cbuff[54] << 8) | i2cbuff[55]; 00182 typ_pm_size_m = stat; 00183 dat = Sps30::CheckCrc2b(stat, i2cbuff[56]); 00184 if(dat == SPSCRCERROR) return SPSCRCERROR; 00185 00186 stat = (i2cbuff[57] << 8) | i2cbuff[58]; 00187 typ_pm_size_l = stat; 00188 dat = Sps30::CheckCrc2b(stat, i2cbuff[59]); 00189 if(dat == SPSCRCERROR) return SPSCRCERROR; 00190 00191 mass_1p0_i = (mass_1p0_m << 16) | mass_1p0_l; 00192 mass_2p5_i = (mass_2p5_m << 16) | mass_2p5_l; 00193 mass_4p0_i = (mass_4p0_m << 16) | mass_4p0_l; 00194 mass_10p0_i = (mass_10p0_m << 16) | mass_10p0_l; 00195 00196 num_0p5_i = (num_0p5_m << 16) | num_0p5_l; 00197 num_1p0_i = (num_1p0_m << 16) | num_1p0_l; 00198 num_2p5_i = (num_2p5_m << 16) | num_2p5_l; 00199 num_4p0_i = (num_4p0_m << 16) | num_4p0_l; 00200 num_10p0_i = (num_10p0_m << 16) | num_10p0_l; 00201 00202 typ_pm_size_i = (typ_pm_size_m << 16) | typ_pm_size_l; 00203 00204 mass_1p0_f = *(float*)&mass_1p0_i; 00205 mass_2p5_f = *(float*)&mass_2p5_i; 00206 mass_4p0_f = *(float*)&mass_4p0_i; 00207 mass_10p0_f = *(float*)&mass_10p0_i; 00208 00209 num_0p5_f = *(float*)&num_0p5_i; 00210 num_1p0_f = *(float*)&num_1p0_i; 00211 num_2p5_f = *(float*)&num_2p5_i; 00212 num_4p0_f = *(float*)&num_4p0_i; 00213 num_10p0_f = *(float*)&num_10p0_i; 00214 00215 typ_pm_size_f = *(float*)&typ_pm_size_i; 00216 00217 return SPSNOERROR; 00218 } 00219 00220 //----------------------------------------------------------------------------- 00221 // Calculate the CRC of a 2 byte value using the SPS30 CRC polynomial 00222 00223 uint8_t Sps30::CalcCrc2b(uint16_t seed) 00224 { 00225 uint8_t bit; // bit mask 00226 uint8_t crc = SPS30_CRC_INIT; // calculated checksum 00227 00228 // calculates 8-Bit checksum with given polynomial 00229 00230 crc ^= (seed >> 8) & 255; 00231 for(bit = 8; bit > 0; --bit) 00232 { 00233 if(crc & 0x80) crc = (crc << 1) ^ SPS30_POLYNOMIAL; 00234 else crc = (crc << 1); 00235 } 00236 00237 crc ^= seed & 255; 00238 for(bit = 8; bit > 0; --bit) 00239 { 00240 if(crc & 0x80) crc = (crc << 1) ^ SPS30_POLYNOMIAL; 00241 else crc = (crc << 1); 00242 } 00243 00244 return crc; 00245 } 00246 00247 //----------------------------------------------------------------------------- 00248 // Compare the CRC values 00249 00250 uint8_t Sps30::CheckCrc2b(uint16_t seed, uint8_t crc_in) 00251 { 00252 uint8_t crc_calc = Sps30::CalcCrc2b(seed); 00253 if(crc_calc != crc_in) return SPSCRCERROR; 00254 return SPSNOERROR; 00255 } 00256 00257 //----------------------------------------------------------------------------- 00258 // Get Sps30 serial number 00259 00260 uint8_t Sps30::GetSerialNumber() 00261 { 00262 i2cbuff[0] = SPS30_CMMD_READ_SERIALNBR >> 8; 00263 i2cbuff[1] = SPS30_CMMD_READ_SERIALNBR & 255; 00264 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00265 if(res) return SPSNOACKERROR; 00266 00267 int i = 0; 00268 for(i = 0; i < sizeof(sn); i++) sn[i] = 0; 00269 for(i = 0; i < sizeof(i2cbuff); i++) i2cbuff[i] = 0; 00270 00271 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, SPS30_SN_SIZE, false); 00272 int t = 0; 00273 for(i = 0; i < SPS30_SN_SIZE; i +=3) { 00274 uint16_t stat = (i2cbuff[i] << 8) | i2cbuff[i + 1]; 00275 sn[i - t] = stat >> 8; 00276 sn[i - t + 1] = stat & 255; 00277 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[i + 2]); 00278 t++; 00279 if(dat == SPSCRCERROR) return SPSCRCERROR; 00280 if(stat == 0) break; 00281 } 00282 00283 return SPSNOERROR; 00284 } 00285 00286 //----------------------------------------------------------------------------- 00287 // Read Auto Cleaning Interval on the SPS30 00288 00289 uint8_t Sps30::ReadAutoCleanInterval() 00290 { 00291 i2cbuff[0] = SPS30_CMMD_AUTO_CLEAN_INTV >> 8; 00292 i2cbuff[1] = SPS30_CMMD_AUTO_CLEAN_INTV & 255; 00293 00294 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00295 if(res) return SPSNOACKERROR; 00296 00297 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 6, false); 00298 00299 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1]; 00300 clean_interval_m = stat; 00301 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]); 00302 if(dat == SPSCRCERROR) return SPSCRCERROR; 00303 00304 stat = (i2cbuff[3] << 8) | i2cbuff[4]; 00305 clean_interval_l = stat; 00306 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]); 00307 if(dat == SPSCRCERROR) return SPSCRCERROR; 00308 00309 clean_interval_i = (clean_interval_m << 16) | clean_interval_l; 00310 00311 return SPSNOERROR; 00312 } 00313 00314 //----------------------------------------------------------------------------- 00315 // Set Auto Cleaning Interval on the SPS30 00316 00317 uint8_t Sps30::SetAutoCleanInterval(uint32_t set_interval) 00318 { 00319 uint16_t set_interval_m = set_interval >> 16; 00320 uint16_t set_interval_l = set_interval & 65535; 00321 00322 i2cbuff[0] = SPS30_CMMD_AUTO_CLEAN_INTV >> 8; 00323 i2cbuff[1] = SPS30_CMMD_AUTO_CLEAN_INTV & 255; 00324 00325 i2cbuff[2] = set_interval_m >> 8; 00326 i2cbuff[3] = set_interval_m & 255; 00327 i2cbuff[4] = Sps30::CalcCrc2b(set_interval_m); 00328 00329 i2cbuff[5] = set_interval_l >> 8; 00330 i2cbuff[6] = set_interval_l & 255; 00331 i2cbuff[7] = Sps30::CalcCrc2b(set_interval_l); 00332 00333 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 8, false); 00334 if(res) return SPSNOACKERROR; 00335 00336 _i2c.read(SPS30_I2C_ADDR | 1, i2cbuff, 6, false); 00337 00338 uint16_t stat = (i2cbuff[0] << 8) | i2cbuff[1]; 00339 clean_interval_m = stat; 00340 uint8_t dat = Sps30::CheckCrc2b(stat, i2cbuff[2]); 00341 if(dat == SPSCRCERROR) return SPSCRCERROR; 00342 00343 stat = (i2cbuff[3] << 8) | i2cbuff[4]; 00344 clean_interval_l = stat; 00345 dat = Sps30::CheckCrc2b(stat, i2cbuff[5]); 00346 if(dat == SPSCRCERROR) return SPSCRCERROR; 00347 00348 clean_interval_i = (clean_interval_m << 16) | clean_interval_l; 00349 00350 return SPSNOERROR; 00351 } 00352 00353 //----------------------------------------------------------------------------- 00354 // Perform manual fan cleaning 00355 00356 uint8_t Sps30::StartFanClean() 00357 { 00358 i2cbuff[0] = SPS30_CMMD_START_FAN_CLEAN >> 8; 00359 i2cbuff[1] = SPS30_CMMD_START_FAN_CLEAN & 255; 00360 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00361 if(res) return SPSNOACKERROR; 00362 return SPSNOERROR; 00363 } 00364 00365 //----------------------------------------------------------------------------- 00366 // Perform a soft reset on the SPS30 00367 00368 uint8_t Sps30::SoftReset() 00369 { 00370 i2cbuff[0] = SPS30_CMMD_SOFT_RESET >> 8; 00371 i2cbuff[1] = SPS30_CMMD_SOFT_RESET & 255; 00372 int res = _i2c.write(SPS30_I2C_ADDR, i2cbuff, 2, false); 00373 if(res) return SPSNOACKERROR; 00374 return SPSNOERROR; 00375 } 00376 00377 /************************** PUBLIC METHODS **********************************/ 00378 00379 //----------------------------------------------------------------------------- 00380 // Initialise SPS30 00381 00382 uint8_t Sps30::InitSPS30() 00383 { 00384 uint8_t dat = Sps30::GetSerialNumber(); 00385 if (dat == SPSNOACKERROR) return DISCONNECTED; 00386 00387 dat = Sps30::StartMeasurement(); 00388 if (dat == SPSNOACKERROR) return DISCONNECTED; 00389 00390 return CONNECTED; 00391 } 00392 00393 //----------------------------------------------------------------------------- 00394 // Poll SPS30 00395 00396 uint8_t Sps30::PollSPS30() 00397 { 00398 uint8_t dat = Sps30::GetReadyStatus(); 00399 if (dat == SPSNOACKERROR) return DISCONNECTED; 00400 00401 if (sps_ready == SPSISREADY) 00402 { 00403 uint8_t crcc = Sps30::ReadMeasurement(); 00404 if (crcc == SPSNOERROR) 00405 { 00406 return DATAREADY; 00407 } 00408 else if (crcc == SPSNOACKERROR) 00409 { 00410 return DISCONNECTED; 00411 } 00412 else 00413 { 00414 return DATAERROR; 00415 } 00416 } 00417 else 00418 { 00419 return DATANOTREADY; 00420 } 00421 }
Generated on Fri Jul 15 2022 18:05:46 by
1.7.2