├── examples ├── Simple_operation │ └── Simple_operation.ino ├── Temperature_Scales │ └── Temperature_Scales.ino ├── Data_Update_speed │ └── Data_Update_speed.ino ├── Tolerances │ └── Tolerances.ino ├── Operation_modes │ └── Operation_modes.ino ├── Absolute_Humidity │ └── Absolute_Humidity.ino └── Calibration │ └── Calibration.ino ├── keywords.txt ├── README.md └── src ├── SHT3x.h └── SHT3x.cpp /examples/Simple_operation/Simple_operation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * The simplest operation using SHT3x 3 | */ 4 | 5 | 6 | #include 7 | SHT3x Sensor; 8 | void setup() { 9 | 10 | Serial.begin(19200); 11 | Sensor.Begin(); 12 | } 13 | 14 | void loop() { 15 | 16 | Sensor.UpdateData(); 17 | Serial.print("Temperature: "); 18 | Serial.print(Sensor.GetTemperature()); 19 | Serial.write("\xC2\xB0"); //The Degree symbol 20 | Serial.println("C"); 21 | Serial.print("Humidity: "); 22 | Serial.print(Sensor.GetRelHumidity()); 23 | Serial.println("%"); 24 | 25 | delay(333); 26 | } 27 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | SHT3x KEYWORD1 2 | Begin KEYWORD2 3 | UpdateData KEYWORD2 4 | GetTemperature KEYWORD2 5 | GetRelHumidity KEYWORD2 6 | GetAbsHumidity KEYWORD2 7 | GetTempTolerance KEYWORD2 8 | GetRelHumTolerance KEYWORD2 9 | GetAbsHumTolerance KEYWORD2 10 | GetError KEYWORD2 11 | SetMode KEYWORD2 12 | SetTemperatureCalibrationFactors KEYWORD2 13 | SetRelHumidityCalibrationFactors KEYWORD2 14 | SetTemperatureCalibrationPoints KEYWORD2 15 | SetRelHumidutyCalibrationPoints KEYWORD2 16 | SoftReset KEYWORD2 17 | HardReset KEYWORD2 18 | HeaterOn KEYWORD2 19 | HeaterOff KEYWORD2 20 | SetAddress KEYWORD2 21 | SetUpdateInterval KEYWORD2 22 | SetTimeout KEYWORD2 23 | ValueIfError KEYWORD2 24 | SHT3xMode KEYWORD2 25 | SHT3xSensor KEYWORD2 26 | TemperatureScale KEYWORD2 27 | AbsHumidityScale KEYWORD2 28 | CalibrationPoints KEYWORD2 29 | CalibrationFactors KEYWORD2 -------------------------------------------------------------------------------- /examples/Temperature_Scales/Temperature_Scales.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 temperature scales are available: 3 | * Celsius (default) 4 | * Fahrenheit 5 | * Kelvin 6 | */ 7 | 8 | 9 | #include 10 | SHT3x Sensor; 11 | void setup() { 12 | 13 | Serial.begin(19200); 14 | Sensor.Begin(); 15 | } 16 | 17 | void loop() { 18 | Sensor.UpdateData(); 19 | 20 | Serial.print(Sensor.GetTemperature()); //Celsius 21 | Serial.write("\xC2\xB0"); //The Degree symbol 22 | Serial.print("C"); 23 | Serial.print(" | "); 24 | 25 | Serial.print(Sensor.GetTemperature(SHT3x::Cel)); //Celsius again 26 | Serial.write("\xC2\xB0"); //The Degree symbol 27 | Serial.print("C"); 28 | Serial.print(" | "); 29 | 30 | Serial.print(Sensor.GetTemperature(SHT3x::Far)); //Fahrenheit 31 | Serial.write("\xC2\xB0"); //The Degree symbol 32 | Serial.print("F"); 33 | Serial.print(" | "); 34 | 35 | Serial.print(Sensor.GetTemperature(SHT3x::Kel)); //Kelvin again 36 | Serial.write("\xC2\xB0"); //The Degree symbol 37 | Serial.print("K"); 38 | 39 | 40 | Serial.println(); 41 | delay(333); 42 | } 43 | -------------------------------------------------------------------------------- /examples/Data_Update_speed/Data_Update_speed.ino: -------------------------------------------------------------------------------- 1 | /*\ 2 | * Changing data update frequency (check for Note 1 in SHT3x.h) 3 | */ 4 | 5 | 6 | #include 7 | SHT3x Sensor_FAST; 8 | SHT3x Sensor_SLOW(0x45); //Set the address by hands 9 | void setup() { 10 | 11 | Serial.begin(19200); 12 | Sensor_FAST.SetUpdateInterval(100); //Data will be updated 10 times per seconds 13 | Sensor_SLOW.SetUpdateInterval(10*1000); //Data will be updated 1 time per 10 seconds 14 | Sensor_FAST.Begin(); 15 | Sensor_SLOW.Begin(); 16 | } 17 | 18 | void loop() { 19 | 20 | Sensor_FAST.UpdateData(); 21 | Sensor_SLOW.UpdateData(); 22 | 23 | Serial.println("Temperature, \xC2\xB0C"); 24 | Serial.print("F: "); Serial.print(Sensor_FAST.GetTemperature(),2); 25 | Serial.print(" | "); 26 | Serial.print("S: "); Serial.print(Sensor_SLOW.GetTemperature(),2); 27 | Serial.println(); 28 | 29 | Serial.println("Relative Humidity, %"); 30 | Serial.print("F: "); Serial.print(Sensor_FAST.GetRelHumidity(),2); 31 | Serial.print(" | "); 32 | Serial.print("S: "); Serial.print(Sensor_SLOW.GetRelHumidity(),2); 33 | delay(333); 34 | } 35 | -------------------------------------------------------------------------------- /examples/Tolerances/Tolerances.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Sometimes you are interesting not in the only values of measurable parameters, 3 | * but in their tolerances too. 4 | * This library supports tolerances for temperature, relative and absolute humidity 5 | * in all scales you can found in corresponding examples. 6 | * 7 | * Tolerances are in dependence from ambient temperature and humidity and sensor model. 8 | * Accuracy grows with a sensor model number: SHT30 15 | SHT3x Sensor; //The default sensor type is SHT30 16 | void setup() { 17 | 18 | Serial.begin(19200); 19 | Sensor.Begin(); 20 | } 21 | 22 | void loop() { 23 | Sensor.UpdateData(); 24 | Serial.print("Temperature: "); 25 | Serial.print(Sensor.GetTemperature(),1); //Celsius 26 | Serial.print(" ± "); 27 | Serial.print(Sensor.GetTempTolerance(),1); 28 | Serial.write("\xC2\xB0"); //The Degree symbol 29 | Serial.print("C"); 30 | 31 | Serial.println(); 32 | 33 | Serial.print("Relative humidity: "); 34 | Serial.print(Sensor.GetRelHumidity(),1); 35 | Serial.print(" ± "); 36 | Serial.print(Sensor.GetRelHumTolerance(),1); 37 | Serial.print("%"); 38 | 39 | Serial.println(); 40 | 41 | Serial.print("Absolute humidity: "); 42 | Serial.print(Sensor.GetAbsHumidity(SHT3x::Pa),1); //Pascal, for example 43 | Serial.print(" ± "); 44 | Serial.print(Sensor.GetAbsHumTolerance(SHT3x::Pa),1); 45 | Serial.print(" Pa"); 46 | 47 | Serial.println(); 48 | delay(333); 49 | } 50 | -------------------------------------------------------------------------------- /examples/Operation_modes/Operation_modes.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Different data acquisition modes. 3 | * The repeatability affects on measurment duration (datasheet/section 2.2): 4 | * Low -> 2.5 ms 5 | * Medium -> 4.5 ms 6 | * High -> 12.5 ms 7 | */ 8 | 9 | #include 10 | 11 | SHT3x Sensor_H(0x44); //Set the sensor address for HIGH repeatablity 12 | //SHT3x Sensor_L(0x45,SHT3x::Single_LowRep_ClockStretch); //The repeatability is not often usable option, 13 | //I think, so I put it to the end of constuctor. So, because we need to define all options, let's do it: 14 | SHT3x Sensor_L( 0x45, //Set the address 15 | SHT3x::Zero, //Functions will return zeros in case of error 16 | 255, //If you DID NOT connected RESET pin 17 | SHT3x::SHT30, //Sensor type 18 | SHT3x::Single_LowRep_ClockStretch //Low repetability mode 19 | ); 20 | 21 | 22 | void setup() { 23 | Serial.begin(19200); 24 | Sensor_H.Begin(); 25 | Sensor_L.Begin(); 26 | 27 | } 28 | 29 | void loop() { 30 | Sensor_H.UpdateData(); 31 | Sensor_L.UpdateData(); 32 | Serial.println("Temperature, \xC2\xB0C"); 33 | Serial.print("H: "); Serial.print(Sensor_H.GetTemperature(),2); 34 | Serial.print(" | "); 35 | Serial.print("L: "); Serial.print(Sensor_L.GetTemperature(),2); 36 | Serial.println(); 37 | 38 | Serial.println("Relative Humidity, %"); 39 | Serial.print("H: "); Serial.print(Sensor_H.GetRelHumidity(),2); 40 | Serial.print(" | "); 41 | Serial.print("L: "); Serial.print(Sensor_L.GetRelHumidity(),2); 42 | delay(333); 43 | } 44 | -------------------------------------------------------------------------------- /examples/Absolute_Humidity/Absolute_Humidity.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Processes in Nature (not the journal) does not takes _relative_ humidity into account. 3 | * They takes into account _absolute_ humidity (water vapor pressure). 4 | * So, that library supports vapor pressure calculation. 5 | * All pressure scales I found in Wikipedia are available: 6 | * mmHg, Torr, 7 | Pa, Bar, 8 | At (Techical atmosphere), 9 | Atm (Standart atmosphere), 10 | mH2O, //O is the letter, not zero 11 | psi, 12 | * (check SHT3x.h, "enum AbsHumidityScale"). 13 | * The absolute humidity tolerance could be recieved in same scales too. 14 | */ 15 | 16 | 17 | #include 18 | SHT3x Sensor; 19 | void setup() { 20 | 21 | Serial.begin(19200); 22 | Sensor.Begin(); 23 | } 24 | 25 | void loop() { 26 | Sensor.UpdateData(); 27 | 28 | Serial.print(Sensor.GetTemperature()); //Celsius 29 | Serial.write("\xC2\xB0"); //The Degree symbol 30 | Serial.print("C"); 31 | Serial.print(" | "); 32 | 33 | Serial.print(Sensor.GetRelHumidity()); 34 | Serial.print("%"); 35 | Serial.print(" | "); 36 | 37 | Serial.print(Sensor.GetAbsHumidity()); //Torr by default 38 | Serial.print(" Torr"); 39 | Serial.print(" | "); 40 | 41 | Serial.print(Sensor.GetAbsHumidity(SHT3x::psi)); //Torr by default 42 | Serial.print(" psi"); 43 | Serial.print(" | "); 44 | 45 | Serial.print(Sensor.GetAbsHumidity(SHT3x::Pa)); //Torr by default 46 | Serial.print(" Pa"); 47 | 48 | //And other... 49 | 50 | Serial.print(" Tolerance: ±"); 51 | Serial.print(Sensor.GetAbsHumTolerance(SHT3x::mH2O)); 52 | Serial.print(" mH2O"); 53 | 54 | 55 | Serial.println(); 56 | delay(333); 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SHT3x 2 | ## Arduino library for Sensirion temperature and humidity sensors SHT30, SHT31 & SHT35. 3 | The heavy version. 4 | Check for /examples for examples of different use cases. 5 | 6 | The datasheet I followed is: 7 | https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf 8 | For more simple version check the SimpleSHT3x library. 9 | 10 | The constructor structure: 11 | SHT3x( int Address = 0x44, //I2C device address, 0x44 or 0x45 12 | ValueIfError Value = Zero, //What to return in case of errors. Zero or PrevValue 13 | uint8_t HardResetPin = 255, //Number of pin RESET connected to (input from 100 to 255 if not used) 14 | SHT3xSensor SensorType = SHT30, //Sensor type, SHT30, SHT31 or SHT35. 15 | SHT3xMode Mode=Single_HighRep_ClockStretch //Operation mode , look for "enum SHT3xMode" 16 | ); 17 | 18 | Do not forget about the UpdateData() method: this method polls sensors. 19 | 20 | 21 | ### Supports: 22 | Temperature data at Celsius, Kelvin and Fahrenheit scales. 23 | Relative humidity data. 24 | Absolute humidity data at Torr, mm Hg, Pa, bar, technical and standard atmosphere, psi scales. 25 | Data integrity (by CRC8 algorithm) (datasheet/section 4.12). 26 | Temperature, relative and absolute humidity tolerances (in dependence from measured values) 27 | Calibration (linear) of temperature and humidity data by factors or by reverse sensor values (2 points) 28 | Heater On/Off (integrated to SHT3x sensor) (datasheet/section 4.10) 29 | Different sensor actions modes (datasheet/section 4.3) 30 | Reset: soft (I2C) and hard (by corresponding pin) (datasheet/section 4.9) 31 | 32 | ### Do not supports: 33 | Action in periodic mode (datasheet/section 4.5) 34 | Interrupts (datasheet/section 3.5) 35 | 36 | 37 | 38 | Note 1: by default, the data from sensor updates not faster, than 2 times a second. 39 | For faster update use SetUpdateInterval(uint32_t UpdateIntervalMillisec); but do not exceed the datasheet values (10 measurments per second (100 ms)) because of sensor self-heating (datasheet/section 4.5, at the end of Table 9) 40 | 41 | Note 2: The sensor type affects the tolerance values only. 42 | 43 | 44 | Created by Risele for everyone's use (profit and non-profit). 45 | 46 | ALL THESE WOR_DS 47 | ARE YOURS EXCEPT 48 | RISELE 49 | ATTEMPT NO 50 | namechangING THERE 51 | USE THEM TOGETHER 52 | USE THEM IN PEACE 53 | -------------------------------------------------------------------------------- /examples/Calibration/Calibration.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * If you found that your sensor is not well-calibrated, you can overcalibrate it (with linear function). 3 | * Calibration translates values recieved from your SHT3x to data that your reference sensor recievs under the same conditions. 4 | * You can overcalibrated both temperature and relative humidity independently. 5 | * Note, that temperature calibration use CELSIUS for overcalculate data: 6 | * FIRST, the temperature converts from sensor byte data to Celsius (check SHT3x::UpdateData), 7 | * SECOND, temperature scales up in respect to calibration. 8 | * THIRD, temperature converts from Celsius to your scale 9 | * You can check SHT3x.cpp, SHT3x::UpdateData and SHT3x::GetTemperature for more information. 10 | * Example for non-celsius scales located at the row 71. 11 | * The same is for relative humidity. 12 | * 13 | * There are two ways for overcalibration: by Factors and by Points. 14 | * By Factors means, that you precalculated your calibration, 15 | * and by Points means, that you have set of TWO experimental points you get from your STH3x and reference sensors. 16 | * The calibration works this way: 17 | * Calibrated_Value = Non_Calibrated_Value * Factor + Shift. 18 | * 19 | * There are two special struct'ures for the calibration needs: 20 | * struct CalibrationFactors 21 | * { 22 | * CalibrationFactors():Factor(1.), Shift(0.){} //predefine values 23 | * float Factor; 24 | * float Shift; 25 | * }; 26 | * 27 | * and 28 | * 29 | * struct CalibrationPoints 30 | * { 31 | * float First; 32 | * float Second; 33 | * }; 34 | * 35 | * For example, let's overcalibrate our sensor: 36 | * by points for relative humidity 37 | * and 38 | * by factors for temperature 39 | */ 40 | 41 | 42 | #include 43 | SHT3x Sensor; //This operates in Celsius 44 | SHT3x Sensor_Far(0x45); //This operates in Fahrenheit 45 | void setup() { 46 | SHT3x::CalibrationPoints HumidityReference; //Points from reference sensor 47 | SHT3x::CalibrationPoints HumiditySHT; //Points from your SHT3x sensor 48 | HumidityReference.First = 0.; //If you really could achieve those ambient conditions, please, call me 8-800-355-... 49 | HumidityReference.Second = 100.; 50 | HumiditySHT.First = 5.3; 51 | HumiditySHT.Second = 97.; 52 | Sensor.SetRelHumidityCalibrationPoints(HumiditySHT, HumidityReference); 53 | 54 | SHT3x::CalibrationFactors TemperatureCalibration; 55 | TemperatureCalibration.Factor = -1.; 56 | TemperatureCalibration.Shift = -1000.; 57 | /*And than use Kelvin, muhaha! 58 | Ok, that was a joke. Here are real values from my expeirence (Celsius): 59 | my SHT30 and trusted instrument have shown 60 | (temperature conditions were similar, we tested it over humidity changes): 61 | SHT30: 23.6 ; 25.1; 62 | TrIns: 22.3 ; 23.7; 63 | So, the overcalibraion equation is: 64 | Trusted_Instrument = SHT30 * 0.9333 + 0.2733, 65 | so 66 | */ 67 | TemperatureCalibration.Factor = 0.9333; 68 | TemperatureCalibration.Shift = 0.2733; 69 | Sensor.SetTemperatureCalibrationFactors(TemperatureCalibration); 70 | 71 | /* FOR OTHER TEMPERATURES SCALES 72 | * First, you have to convert data you use for calibration to Celsius. 73 | * For example, if I use Fahrenheit in both SHT and reference sensors and got the next data set: 74 | * SHT Ref //Fahrenheit 75 | * 32 35 76 | * 50 52 77 | * 167 180 78 | * I have to convert it to Celsius: 79 | * SHT Ref //Celsius 80 | * 0 1.7 81 | * 10 11.1 82 | * 75 82.2 83 | * For this particular dataset overcalibration is the following (linear approximation by Microsoft Excel): 84 | */ 85 | TemperatureCalibration.Factor = 1.0807; //We have already set calibration for Celsius sensor, 86 | TemperatureCalibration.Shift = 1.0467; //so, there is no need for a new variable 87 | Sensor_Far.SetTemperatureCalibrationFactors(TemperatureCalibration); 88 | Serial.begin(19200); 89 | Sensor.Begin(); 90 | Sensor_Far.Begin(); 91 | } 92 | 93 | void loop() { 94 | Sensor.UpdateData(); 95 | 96 | Serial.print(Sensor.GetTemperature()); //Celsius 97 | Serial.write("\xC2\xB0"); //The Degree symbol 98 | Serial.print("C"); 99 | Serial.print(" | "); 100 | 101 | Serial.print(Sensor.GetRelHumidity()); 102 | Serial.write("%"); 103 | 104 | //And, for an Fahreneit sensor: 105 | Sensor_Far.UpdateData(); 106 | Serial.print(Sensor_Far.GetTemperature(SHT3x::Far)); 107 | Serial.write("\xC2\xB0"); //The Degree symbol 108 | Serial.print("F"); 109 | Serial.println(); 110 | delay(333); 111 | } 112 | -------------------------------------------------------------------------------- /src/SHT3x.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino library for Sensirion temperature and humidity sensors SHT30, SHT31 & SHT35. 3 | the heavy version. 4 | Check for /examples for examples of different use cases. 5 | 6 | The datasheet I followed is: 7 | https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf 8 | For more simple version check the SimpleSHT3x library. 9 | 10 | The constructor structure: 11 | SHT3x( int Address = 0x44, //I2C device address, 0x44 or 0x45 12 | ValueIfError Value = Zero, //What to return in case of errors. Zero or PrevValue 13 | uint8_t HardResetPin = 255, //Number of pin RESET connected to (input from 100 to 255 if not used) 14 | SHT3xSensor SensorType = SHT30, //Sensor type, SHT30, SHT31 or SHT35. 15 | SHT3xMode Mode=Single_HighRep_ClockStretch //Operation mode , look for "enum SHT3xMode" 16 | ); 17 | 18 | Supports: 19 | Temperature data at Celsius, Kelvin and Fahrenheit scales. 20 | Relative humidity data. 21 | Absolute humidity data at Torr, mm Hg, Pa, bar, technical and standard atmosphere, psi scales. 22 | Data integrity (by CRC8 algorithm) (datasheet/section 4.12). 23 | Temperature, relative and absolute humidity tolerances (in dependence from measured values) 24 | Calibration (linear) of temperature and humidity data by factors or by reverse sensor values (2 points) 25 | Heater On/Off (integrated to SHT3x sensor) (datasheet/section 4.10) 26 | Different sensor actions modes (datasheet/section 4.3) 27 | Reset: soft (I2C) and hard (by corresponding pin) (datasheet/section 4.9) 28 | 29 | Do not supports: 30 | Action in periodic mode (datasheet/section 4.5) 31 | Interrupts (datasheet/section 3.5) 32 | 33 | 34 | 35 | Note 1: by default, the data from sensor updates not faster, than 2 times a second. 36 | For faster update use SetUpdateInterval(uint32_t UpdateIntervalMillisec); but do not exceed the datasheet values (10 measurments per second (100 ms)) because of sensor self-heating (datasheet/section 4.5, at the end of Table 9) 37 | 38 | Note 2: The sensor type affects the tolerance values only. 39 | 40 | 41 | Created by Risele for everyone's use (profit and non-profit). 42 | 43 | ALL THESE WOR_DS 44 | ARE YOURS EXCEPT 45 | RISELE 46 | ATTEMPT NO 47 | namechangING THERE 48 | USE THEM TOGETHER 49 | USE THEM IN PEACE 50 | 51 | */ 52 | 53 | 54 | #ifndef SHT3x_h 55 | #define SHT3x_h 56 | 57 | 58 | //Arduino standart libraries 59 | #if defined(ARDUINO) && ARDUINO >= 100 60 | #include "Arduino.h" 61 | #else 62 | #include "WProgram.h" 63 | #endif 64 | //Arduino I2C/TWI library 65 | #include 66 | //For calculating the tolerance of absolute humidity 67 | #include 68 | 69 | 70 | class SHT3x 71 | { 72 | public: 73 | enum ValueIfError //Define, what to return in case of error: Zero or previous value 74 | { 75 | Zero, 76 | PrevValue 77 | }; 78 | enum SHT3xMode 79 | { 80 | Single_HighRep_ClockStretch, 81 | Single_MediumRep_ClockStretch, 82 | Single_LowRep_ClockStretch, 83 | Single_HighRep_NoClockStretch, 84 | Single_MediumRep_NoClockStretch, 85 | Single_LowRep_NoClockStretch 86 | }; 87 | enum SHT3xSensor 88 | { 89 | SHT30, 90 | SHT31, 91 | SHT35 92 | }; 93 | enum TemperatureScale 94 | { 95 | Cel, 96 | Far, 97 | Kel 98 | }; 99 | enum AbsHumidityScale 100 | { 101 | mmHg, 102 | Torr, //same as mm Hg 103 | Pa, 104 | Bar, 105 | At, //Techical atmosphere 106 | Atm, //Standart atmosphere 107 | mH2O, 108 | psi, 109 | }; 110 | struct CalibrationPoints 111 | { 112 | float First; 113 | float Second; 114 | }; 115 | struct CalibrationFactors 116 | { 117 | CalibrationFactors():Factor(1.), Shift(0.){} 118 | float Factor; 119 | float Shift; 120 | }; 121 | 122 | SHT3x( int Address = 0x44, 123 | ValueIfError Value = Zero, 124 | uint8_t HardResetPin = 255, 125 | SHT3xSensor SensorType = SHT30, 126 | SHT3xMode Mode=Single_HighRep_ClockStretch); 127 | 128 | void Begin( int SDA = 0, 129 | int SCL = 0); 130 | void UpdateData(int SDA = 0); 131 | 132 | float GetTemperature(TemperatureScale Degree = Cel); 133 | float GetRelHumidity(); 134 | float GetAbsHumidity(AbsHumidityScale Scale = Torr); 135 | float GetTempTolerance(TemperatureScale Degree = Cel, SHT3xSensor SensorType = SHT30); 136 | float GetRelHumTolerance(SHT3xSensor SensorType = SHT30); 137 | float GetAbsHumTolerance(AbsHumidityScale Scale = Torr, SHT3xSensor SensorType = SHT30); 138 | 139 | 140 | uint8_t GetError(); 141 | 142 | void SetMode(SHT3xMode Mode = Single_HighRep_ClockStretch); 143 | void SetTemperatureCalibrationFactors(CalibrationFactors TemperatureCalibration); 144 | void SetRelHumidityCalibrationFactors(CalibrationFactors RelHumidityCalibration); 145 | void SetTemperatureCalibrationPoints(CalibrationPoints SensorValues, CalibrationPoints Reference); 146 | void SetRelHumidityCalibrationPoints(CalibrationPoints SensorValues, CalibrationPoints Reference); 147 | 148 | void SoftReset(int SDA = 0); 149 | void HardReset(); 150 | 151 | void HeaterOn(int SDA = 0); 152 | void HeaterOff(int SDA = 0); 153 | 154 | void SetAddress(uint8_t NewAddress); 155 | void SetUpdateInterval(uint32_t UpdateIntervalMillisec); 156 | void SetTimeout(uint32_t TimeoutMillisec); 157 | 158 | 159 | 160 | private: 161 | float _TemperatureCeil; 162 | float _RelHumidity; 163 | bool _OperationEnabled = false; 164 | uint8_t _HardResetPin; 165 | ValueIfError _ValueIfError; 166 | uint8_t _MeasLSB; //Data read command, Most Significant Byte 167 | uint8_t _MeasMSB; //Data read command, Most Significant Byte 168 | uint8_t _Address; 169 | SHT3xSensor _SensorType; 170 | uint32_t _UpdateIntervalMillisec = 500; 171 | uint32_t _LastUpdateMillisec = 0; 172 | uint32_t _TimeoutMillisec = 100; 173 | void SendCommand(uint8_t MSB, uint8_t LSB, int SDA = 0); 174 | bool CRC8(uint8_t MSB, uint8_t LSB, uint8_t CRC); 175 | float ReturnValueIfError(float Value); 176 | void ToReturnIfError(ValueIfError Value); 177 | CalibrationFactors _TemperatureCalibration; 178 | CalibrationFactors _RelHumidityCalibration; 179 | 180 | /* 181 | * Factors for poly for calculating absolute humidity (in Torr): 182 | * P = (RelativeHumidity /100%) * sum(_AbsHumPoly[i]*T^i) 183 | * where P is absolute humidity (Torr/mm Hg), 184 | * T is Temperature(Kelvins degree) / 1000, 185 | * ^ means power. 186 | * For more data, check the NIST chemistry webbook: 187 | * http://webbook.nist.gov/cgi/cbook.cgi?ID=C7732185&Units=SI&Mask=4&Type=ANTOINE&Plot=on#ANTOINE 188 | */ 189 | float _AbsHumPoly[6] ={-157.004, 3158.0474, -25482.532, 103180.197, -209805.497, 171539.883}; 190 | 191 | enum Errors 192 | { 193 | noError = 0, 194 | Timeout = 1, 195 | DataCorrupted = 2, 196 | WrongAddress = 3, 197 | //I2C errors 198 | TooMuchData = 4, 199 | AddressNACK = 5, 200 | DataNACK = 6, 201 | OtherI2CError = 7, 202 | UnexpectedError = 8 203 | } _Error; 204 | void I2CError(uint8_t I2Canswer); 205 | 206 | }; 207 | #endif //SHT3x_h 208 | -------------------------------------------------------------------------------- /src/SHT3x.cpp: -------------------------------------------------------------------------------- 1 | #include "SHT3x.h" 2 | SHT3x::SHT3x(int Address, ValueIfError Value, uint8_t HardResetPin, SHT3xSensor SensorType, SHT3xMode Mode) 3 | { 4 | _Error = noError; 5 | SetAddress((uint8_t)Address); 6 | _ValueIfError = Value; 7 | SetMode(Mode); 8 | _SensorType = SensorType; 9 | _HardResetPin = HardResetPin ; 10 | 11 | } 12 | 13 | void SHT3x::Begin(int SDA, int SCL) 14 | { 15 | if (SDA==0) Wire.begin(); 16 | else Wire1.begin(SDA, SCL); 17 | _OperationEnabled = true; 18 | } 19 | 20 | void SHT3x::UpdateData(int SDA) 21 | { 22 | _Error = noError; 23 | if ((_LastUpdateMillisec == 0) || ((millis()-_LastUpdateMillisec)>=_UpdateIntervalMillisec)) 24 | { 25 | SendCommand(_MeasMSB,_MeasLSB,SDA); 26 | if (_Error == noError) 27 | { 28 | if (SDA==0) 29 | { 30 | Wire.requestFrom(_Address, (uint8_t)6); 31 | uint32_t WaitingBeginTime = millis(); 32 | while ((Wire.available()<6) && ((millis() - WaitingBeginTime) < _TimeoutMillisec)) 33 | { 34 | //Do nothing, just wait 35 | } 36 | if ((millis() - WaitingBeginTime) < _TimeoutMillisec) 37 | { 38 | _LastUpdateMillisec = WaitingBeginTime; 39 | uint8_t data[6]; 40 | for (uint8_t i = 0; i<6; i++) 41 | { 42 | data[i] = Wire.read(); 43 | } 44 | 45 | if ((CRC8(data[0],data[1],data[2])) && (CRC8(data[3],data[4],data[5]))) 46 | { 47 | uint16_t TemperatureRaw = (data[0]<<8)+(data[1]<<0); 48 | uint16_t RelHumidityRaw = (data[3]<<8)+(data[4]<<0); 49 | _TemperatureCeil = ((float) TemperatureRaw) * 0.00267033 - 45.; 50 | _TemperatureCeil = _TemperatureCeil*_TemperatureCalibration.Factor + 51 | _TemperatureCalibration.Shift; 52 | _RelHumidity = ((float) RelHumidityRaw) * 0.0015259; 53 | _RelHumidity = _RelHumidity * _RelHumidityCalibration.Factor + 54 | _RelHumidityCalibration.Shift; 55 | 56 | _Error = noError; 57 | } 58 | else 59 | { 60 | _Error = DataCorrupted; 61 | } 62 | } 63 | else //Timeout 64 | { 65 | _Error = Timeout; 66 | } 67 | } 68 | else 69 | { 70 | Wire1.requestFrom(_Address, (uint8_t)6); 71 | uint32_t WaitingBeginTime = millis(); 72 | while ((Wire1.available()<6) && ((millis() - WaitingBeginTime) < _TimeoutMillisec)) 73 | { 74 | //Do nothing, just wait 75 | } 76 | if ((millis() - WaitingBeginTime) < _TimeoutMillisec) 77 | { 78 | _LastUpdateMillisec = WaitingBeginTime; 79 | uint8_t data[6]; 80 | for (uint8_t i = 0; i<6; i++) 81 | { 82 | data[i] = Wire1.read(); 83 | } 84 | 85 | if ((CRC8(data[0],data[1],data[2])) && (CRC8(data[3],data[4],data[5]))) 86 | { 87 | uint16_t TemperatureRaw = (data[0]<<8)+(data[1]<<0); 88 | uint16_t RelHumidityRaw = (data[3]<<8)+(data[4]<<0); 89 | _TemperatureCeil = ((float) TemperatureRaw) * 0.00267033 - 45.; 90 | _TemperatureCeil = _TemperatureCeil*_TemperatureCalibration.Factor + 91 | _TemperatureCalibration.Shift; 92 | _RelHumidity = ((float) RelHumidityRaw) * 0.0015259; 93 | _RelHumidity = _RelHumidity * _RelHumidityCalibration.Factor + 94 | _RelHumidityCalibration.Shift; 95 | 96 | _Error = noError; 97 | } 98 | else 99 | { 100 | _Error = DataCorrupted; 101 | } 102 | } 103 | else //Timeout 104 | { 105 | _Error = Timeout; 106 | } 107 | } 108 | } 109 | else //Error after message send 110 | { 111 | // Nothing to do, measurement commands will return NULL because of Error != noError 112 | } 113 | } 114 | else //LastUpdate was too recently 115 | { 116 | //Nothing to do, wait for next call 117 | } 118 | } 119 | 120 | float SHT3x::GetTemperature(TemperatureScale Degree) 121 | { 122 | //default scale is Celsius 123 | //At first, calculate in Celsius, than, if need, recalculate to Farenheit or Kelvin and than adjust according to calibration; 124 | float Temperature = _TemperatureCeil; 125 | if (Degree == Kel) 126 | { 127 | Temperature+=273.15; 128 | } 129 | else if (Degree == Far) 130 | { 131 | Temperature = Temperature*1.8+32.; 132 | } 133 | 134 | return ReturnValueIfError(Temperature); 135 | } 136 | 137 | float SHT3x::GetRelHumidity() 138 | { 139 | return ReturnValueIfError(_RelHumidity); 140 | } 141 | 142 | float SHT3x::GetAbsHumidity(AbsHumidityScale Scale) 143 | { 144 | float millikelvins = GetTemperature(Kel) / 1000.; 145 | float Pressure = 0.; 146 | for (uint8_t i = 0; i<6; i++) 147 | { 148 | float term = 1.; 149 | for (uint8_t j = 0; j 65.) 221 | { 222 | //Linear from 0.2 at 65 C to 0.6 at 125 C. 223 | Tolerance = 0.0067 * Temperature - 0.2333; 224 | } 225 | else //if (Temperature < 0.) 226 | { 227 | //Linear from 0.6 at -40 C to 0.2 at 0 C. 228 | Tolerance = -0.01 * Temperature + 0.2; 229 | } 230 | break; 231 | } 232 | case SHT31: 233 | { 234 | if ((0. <= Temperature) && (Temperature <= 90.)) 235 | { 236 | Tolerance = 0.2; 237 | } 238 | else if (Temperature > 65.) 239 | { 240 | //Linear from 0.2 at 90 C to 0.5 at 125 C. 241 | Tolerance = 0.0086 * Temperature - 0.5714; 242 | } 243 | else //if (Temperature < 0.) 244 | { 245 | //Linear from 0.3 at -40 C to 0.2 at 0 C. 246 | Tolerance = -0.0025 * Temperature + 0.2; 247 | } 248 | break; 249 | } 250 | case SHT35: 251 | { 252 | if (Temperature <= 0.) 253 | { 254 | Tolerance = 0.2; 255 | } 256 | else if ((0. < Temperature) && (Temperature <= 20.)) 257 | { 258 | //Linear from 0.2 at 0 C to 0.1 at 20 C. 259 | Tolerance = -0.005 * Temperature + 0.2; 260 | } 261 | else if ((20. < Temperature) && (Temperature <= 60.)) 262 | { 263 | Tolerance = 0.1; 264 | } 265 | else if ((60. < Temperature) && (Temperature <= 90.)) 266 | { 267 | //Linear from 0.1 at 60 C to 0.2 at 90 C. 268 | Tolerance = -0.0033 * Temperature - 0.1; 269 | } 270 | else //if (90. < Temperature) 271 | { 272 | //Linear from 0.2 at 90 C to 0.4 at 125 C. 273 | Tolerance = 0.0057 * Temperature - 0.3143; 274 | } 275 | break; 276 | } 277 | } 278 | if (Degree == Far) 279 | { 280 | Tolerance *= 1.8; 281 | } 282 | 283 | 284 | return ReturnValueIfError(Tolerance); 285 | } 286 | 287 | float SHT3x::GetRelHumTolerance(SHT3xSensor SensorType) 288 | { 289 | float RelHumidity = GetRelHumidity(); 290 | float Tolerance; 291 | switch (SensorType) 292 | { 293 | case SHT30: 294 | { 295 | if ((10.<= RelHumidity) && (RelHumidity <= 90.)) 296 | { 297 | Tolerance = 2.; 298 | } 299 | else if (RelHumidity < 10.) 300 | { 301 | //Linear from 4 at 0% to 2 at 10% 302 | Tolerance = -0.2 * RelHumidity + 4.; 303 | } 304 | else 305 | { 306 | //Linear from 2 at 90% to 4 at 100% 307 | Tolerance = 0.2 * RelHumidity - 16.; 308 | } 309 | break; 310 | } 311 | case SHT31: 312 | { 313 | Tolerance = 2.; 314 | break; 315 | } 316 | case SHT35: 317 | { 318 | if (RelHumidity <= 80.) 319 | { 320 | Tolerance = 1.5; 321 | } 322 | else //if (80 < RelHumidity) 323 | { 324 | //Linear from 0.5 at 80% to 2 at 100% 325 | Tolerance = 0.025 * RelHumidity - 0.5; 326 | } 327 | break; 328 | } 329 | } 330 | return ReturnValueIfError(Tolerance); 331 | 332 | } 333 | 334 | float SHT3x::GetAbsHumTolerance(AbsHumidityScale Scale, SHT3xSensor SensorType) 335 | { 336 | /* Dependence of absolute humidity is similar (from 0 to 80C) to P = H*a*exp(b*T), 337 | * where P is absolute humidity, H is relative humidity, T is temperature (Celsius), 338 | * a ~= 0.0396, b~=0.0575. 339 | * So its relative tolerance dP/P = square root [ (dH/H)^2 + (b*dT)^2 ]. 340 | */ 341 | 342 | float RelHumidityRelTolerance = GetRelHumTolerance(SensorType)/GetRelHumidity(); 343 | float TemperatureRelTolerance = 0.0575*GetTempTolerance(Cel, SensorType); 344 | RelHumidityRelTolerance*=RelHumidityRelTolerance; 345 | TemperatureRelTolerance*=TemperatureRelTolerance; 346 | return ReturnValueIfError( 347 | GetAbsHumidity(Scale) * sqrt(RelHumidityRelTolerance+TemperatureRelTolerance) 348 | ); 349 | } 350 | 351 | void SHT3x::SetMode(SHT3xMode Mode) 352 | { 353 | switch (Mode) 354 | { 355 | case Single_HighRep_ClockStretch: 356 | { 357 | _MeasMSB=0x2C; 358 | _MeasLSB=0x06; 359 | break; 360 | } 361 | case Single_MediumRep_ClockStretch: 362 | { 363 | _MeasMSB=0x2C; 364 | _MeasLSB=0x0D; 365 | break; 366 | } 367 | case Single_LowRep_ClockStretch: 368 | { 369 | _MeasMSB=0x2C; 370 | _MeasLSB=0x10; 371 | break; 372 | } 373 | case Single_HighRep_NoClockStretch: 374 | { 375 | _MeasMSB=0x24; 376 | _MeasLSB=0x00; 377 | break; 378 | } 379 | case Single_MediumRep_NoClockStretch: 380 | { 381 | _MeasMSB=0x24; 382 | _MeasLSB=0x0B; 383 | break; 384 | } 385 | case Single_LowRep_NoClockStretch: 386 | { 387 | _MeasMSB=0x24; 388 | _MeasLSB=0x16; 389 | break; 390 | } 391 | default: 392 | { 393 | _MeasMSB=0x2C; 394 | _MeasLSB=0x06; 395 | break; 396 | } 397 | 398 | } 399 | } 400 | 401 | void SHT3x::SetTemperatureCalibrationFactors(CalibrationFactors TemperatureCalibration) 402 | { 403 | _TemperatureCalibration = TemperatureCalibration; 404 | } 405 | 406 | void SHT3x::SetRelHumidityCalibrationFactors(CalibrationFactors RelHumidityCalibration) 407 | { 408 | _RelHumidityCalibration = RelHumidityCalibration; 409 | } 410 | 411 | void SHT3x::SetTemperatureCalibrationPoints(CalibrationPoints SensorValues, CalibrationPoints Reference) 412 | { 413 | _TemperatureCalibration.Factor = (Reference.Second - Reference.First) / (SensorValues.Second - SensorValues.First); 414 | _TemperatureCalibration.Shift = Reference.First - _TemperatureCalibration.Factor * SensorValues.First; 415 | } 416 | 417 | void SHT3x::SetRelHumidityCalibrationPoints(CalibrationPoints SensorValues, CalibrationPoints Reference) 418 | { 419 | _RelHumidityCalibration.Factor = (Reference.Second - Reference.First) / (SensorValues.Second - SensorValues.First); 420 | _RelHumidityCalibration.Shift = Reference.First - _RelHumidityCalibration.Factor * SensorValues.First; 421 | } 422 | 423 | void SHT3x::SoftReset(int SDA) 424 | { 425 | SendCommand(0x30, 0xA2, SDA); 426 | } 427 | 428 | void SHT3x::HardReset() 429 | { 430 | if (_HardResetPin<100) //MEGA2560 have only 68 pins 431 | { 432 | pinMode(_HardResetPin,OUTPUT); 433 | digitalWrite(_HardResetPin,LOW); 434 | delayMicroseconds(1); //Reset pin have to be LOW at least 350ns, so 1 usec is enough. I think, there is no need for micros() for 1 usec. 435 | digitalWrite(_HardResetPin,HIGH); 436 | } 437 | } 438 | 439 | void SHT3x::HeaterOn(int SDA) 440 | { 441 | SendCommand(0x30, 0x6D, SDA); 442 | } 443 | 444 | void SHT3x::HeaterOff(int SDA) 445 | { 446 | SendCommand(0x30, 0x66, SDA); 447 | } 448 | 449 | void SHT3x::SetAddress(uint8_t Address) 450 | { 451 | if ((Address == 0x44) || (Address == 0x45)) 452 | { 453 | _Address = Address; 454 | } 455 | else 456 | { 457 | _Error = WrongAddress; 458 | } 459 | } 460 | 461 | void SHT3x::SetUpdateInterval(uint32_t UpdateIntervalMillisec) 462 | { 463 | if (UpdateIntervalMillisec > 0) 464 | { 465 | _UpdateIntervalMillisec = UpdateIntervalMillisec; 466 | } 467 | } 468 | 469 | void SHT3x::SetTimeout(uint32_t TimeoutMillisec) 470 | { 471 | if (TimeoutMillisec > 0) 472 | { 473 | _TimeoutMillisec = _TimeoutMillisec; 474 | } 475 | } 476 | 477 | void SHT3x::I2CError(uint8_t I2Canswer) 478 | { 479 | switch (I2Canswer) 480 | { 481 | case 0: 482 | { 483 | _Error = noError; 484 | break; 485 | } 486 | case 1: 487 | { 488 | _Error = TooMuchData; 489 | break; 490 | } 491 | case 2: 492 | { 493 | _Error = AddressNACK; 494 | break; 495 | } 496 | case 3: 497 | { 498 | _Error = DataNACK; 499 | break; 500 | } 501 | case 4: 502 | { 503 | _Error = OtherI2CError; 504 | break; 505 | } 506 | default: 507 | { 508 | _Error = UnexpectedError; 509 | break; 510 | } 511 | } 512 | } 513 | 514 | void SHT3x::SendCommand(uint8_t MSB, uint8_t LSB, int SDA) 515 | { 516 | if (_OperationEnabled) 517 | { 518 | //Everything is OK, nothing to do 519 | } 520 | else 521 | { 522 | if (SDA==0) Wire.begin(); 523 | else Wire1.begin(); 524 | _OperationEnabled = true; 525 | } 526 | if (SDA==0) 527 | { 528 | Wire.beginTransmission(_Address); 529 | // Send Soft Reset command 530 | Wire.write(MSB); 531 | Wire.write(LSB); 532 | // Stop I2C transmission 533 | uint8_t success = Wire.endTransmission(); 534 | } 535 | else 536 | { 537 | Wire1.beginTransmission(_Address); 538 | // Send Soft Reset command 539 | Wire1.write(MSB); 540 | Wire1.write(LSB); 541 | // Stop I2C transmission 542 | uint8_t success = Wire1.endTransmission(); 543 | } 544 | } 545 | 546 | bool SHT3x::CRC8(uint8_t MSB, uint8_t LSB, uint8_t CRC) 547 | { 548 | /* 549 | * Name : CRC-8 550 | * Poly : 0x31 x^8 + x^5 + x^4 + 1 551 | * Init : 0xFF 552 | * Revert: false 553 | * XorOut: 0x00 554 | * Check : for 0xBE,0xEF CRC is 0x92 555 | */ 556 | uint8_t crc = 0xFF; 557 | uint8_t i; 558 | crc ^=MSB; 559 | 560 | for (i = 0; i < 8; i++) 561 | crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1; 562 | 563 | crc ^= LSB; 564 | for (i = 0; i < 8; i++) 565 | crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1; 566 | 567 | if (crc==CRC) 568 | { 569 | return true; 570 | } 571 | else 572 | { 573 | return false; 574 | } 575 | } 576 | 577 | uint8_t SHT3x::GetError() 578 | { 579 | return _Error; 580 | } 581 | 582 | float SHT3x::ReturnValueIfError(float Value) 583 | { 584 | if (_Error == noError) 585 | { 586 | return Value; 587 | } 588 | else 589 | { 590 | if (_ValueIfError == PrevValue) 591 | { 592 | return Value; 593 | } 594 | else 595 | { 596 | return 0.; 597 | } 598 | } 599 | } 600 | 601 | void SHT3x::ToReturnIfError(ValueIfError Value) 602 | { 603 | _ValueIfError = Value; 604 | } 605 | 606 | --------------------------------------------------------------------------------