IZU2020 / SPS30

Dependents:   IZU2021_SPS30 Hybrid_IZU2021_MISSION_v2 Hybrid_IZU2021_MISSION

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sps30.cpp Source File

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 }