/// <summary> /// Reads the compensation data. /// </summary> /// <remarks> /// The compensation data is written to the chip at the time of manufacture and cannot be changed. /// This information is used to convert the readings from the sensor into actual temperature, /// pressure and humidity readings. /// From the data sheet, the register addresses and length are: /// Temperature and pressure: start address 0x88, end address 0x9F (length = 24) /// Humidity 1: 0xa1, length = 1 /// Humidity 2 and 3: start address 0xe1, end address 0xe7, (length = 8) /// </remarks> private void ReadCompensationData() { var temperatureAndPressureData = _bme280.ReadRegisters(0x88, 24); var humidityData1 = _bme280.ReadRegisters(0xa1, 1); var humidityData2To6 = _bme280.ReadRegisters(0xe1, 7); _compensationData.T1 = (ushort)(temperatureAndPressureData[0] + (temperatureAndPressureData[1] << 8)); _compensationData.T2 = (short)(temperatureAndPressureData[2] + (temperatureAndPressureData[3] << 8)); _compensationData.T3 = (short)(temperatureAndPressureData[4] + (temperatureAndPressureData[5] << 8)); // _compensationData.P1 = (ushort)(temperatureAndPressureData[6] + (temperatureAndPressureData[7] << 8)); _compensationData.P2 = (short)(temperatureAndPressureData[8] + (temperatureAndPressureData[9] << 8)); _compensationData.P3 = (short)(temperatureAndPressureData[10] + (temperatureAndPressureData[11] << 8)); _compensationData.P4 = (short)(temperatureAndPressureData[12] + (temperatureAndPressureData[13] << 8)); _compensationData.P5 = (short)(temperatureAndPressureData[14] + (temperatureAndPressureData[15] << 8)); _compensationData.P6 = (short)(temperatureAndPressureData[16] + (temperatureAndPressureData[17] << 8)); _compensationData.P7 = (short)(temperatureAndPressureData[18] + (temperatureAndPressureData[19] << 8)); _compensationData.P8 = (short)(temperatureAndPressureData[20] + (temperatureAndPressureData[21] << 8)); _compensationData.P9 = (short)(temperatureAndPressureData[22] + (temperatureAndPressureData[23] << 8)); // _compensationData.H1 = humidityData1[0]; _compensationData.H2 = (short)(humidityData2To6[0] + (humidityData2To6[1] << 8)); _compensationData.H3 = humidityData2To6[2]; _compensationData.H4 = (short)((humidityData2To6[3] << 4) + (humidityData2To6[4] & 0xf)); _compensationData.H5 = (short)(((humidityData2To6[4] & 0xf) >> 4) + (humidityData2To6[5] << 4)); _compensationData.H6 = (sbyte)humidityData2To6[6]; }
/// <summary> /// Create a new TMP102 object using the default configuration for the sensor. /// </summary> /// <param name="address">I2C address of the sensor.</param> /// <param name="speed">Speed of the communication with the sensor.</param> public TMP102(byte address = 0x48, ushort speed = 100, ushort updateInterval = MinimumPollingPeriod, float temperatureChangeNotificationThreshold = 0.001F) { if ((speed < 10) || (speed > 1000)) { throw new ArgumentOutOfRangeException(nameof(speed), "Speed should be 10 KHz to 3,400 KHz."); } if (temperatureChangeNotificationThreshold < 0) { throw new ArgumentOutOfRangeException(nameof(temperatureChangeNotificationThreshold), "Temperature threshold should be >= 0"); } if ((updateInterval != 0) && (updateInterval < MinimumPollingPeriod)) { throw new ArgumentOutOfRangeException(nameof(updateInterval), "Update period should be 0 or >= than " + MinimumPollingPeriod); } TemperatureChangeNotificationThreshold = temperatureChangeNotificationThreshold; _updateInterval = updateInterval; _tmp102 = new I2CBus(address, speed); var configuration = _tmp102.ReadRegisters(0x01, 2); _sensorResolution = (configuration[1] & 0x10) > 0 ? Resolution.Resolution13Bits : Resolution.Resolution12Bits; if (updateInterval > 0) { StartUpdating(); } else { Update(); } }
/// <summary> /// Update the temperature and pressure from the sensor and set the Pressure property. /// </summary> public void Update() { // // Tell the sensor to take a temperature and pressure reading, wait for // 3ms (see section 2.2 of the datasheet) and then read the ADC values. // _mpl115a2.WriteBytes(new byte[] { Registers.StartConversion, 0x00 }); Thread.Sleep(5); var data = _mpl115a2.ReadRegisters(Registers.PressureMSB, 4); // // Extract the sensor data, note that this is a 10-bit reading so move // the data right 6 bits (see section 3.1 of the datasheet). // var pressure = (ushort)(((data[0] << 8) + data[1]) >> 6); var temperature = (ushort)(((data[2] << 8) + data[3]) >> 6); Temperature = (float)((temperature - 498.0) / -5.35) + 25; // // Now use the calculations in section 3.2 to determine the // current pressure reading. // const double PRESSURE_CONSTANT = 65.0 / 1023.0; var compensatedPressure = _coefficients.A0 + ((_coefficients.B1 + (_coefficients.C12 * temperature)) * pressure) + (_coefficients.B2 * temperature); Pressure = (float)(PRESSURE_CONSTANT * compensatedPressure) + 50; }
/// <summary> /// Read the six sensor bytes and set the values for the X, Y and Z acceleration. /// </summary> /// <remarks> /// All six acceleration registers should be read at the same time to ensure consistency /// of the measurements. /// </remarks> public void Update() { var data = _adxl345.ReadRegisters(Registers.X0, 6); X = (short)(data[0] + (data[1] << 8)); Y = (short)(data[2] + (data[3] << 8)); Z = (short)(data[4] + (data[5] << 8)); if ((_updateInterval != 0) && ((Math.Abs(X - _lastX) > AccelerationChangeNotificationThreshold) || (Math.Abs(Y - _lastY) > AccelerationChangeNotificationThreshold) || (Math.Abs(Z - _lastZ) > AccelerationChangeNotificationThreshold))) { Vector lastNotifiedReading = new Vector(_lastX, _lastY, _lastZ); Vector currentReading = new Vector(X, Y, Z); _lastX = X; _lastY = Y; _lastZ = Z; AccelerationChanged(this, new SensorVectorEventArgs(lastNotifiedReading, currentReading)); } }
/// <summary> /// Force the sensor to make a reading and update the relevant properties. /// </summary> public void Update() { int temp = 0; // // Get the humidity first. // _groveTH02.WriteRegister(Registers.Config, StartMeasurement); // // Maximum conversion time should be 40ms but loop just in case // it takes longer. // Thread.Sleep(40); while ((_groveTH02.ReadRegister(Registers.Status) & 0x01) > 0) { ; } byte[] data = _groveTH02.ReadRegisters(Registers.DataHigh, 2); temp = data[0] << 8; temp |= data[1]; temp >>= 4; Humidity = (((float)temp) / 16) - 24; // // Now get the temperature. // _groveTH02.WriteRegister(Registers.Config, StartMeasurement | MeasureTemperature); // // Maximum conversion time should be 40ms but loop just in case // it takes longer. // Thread.Sleep(40); while ((_groveTH02.ReadRegister(Registers.Status) & 0x01) > 0) { ; } data = _groveTH02.ReadRegisters(Registers.DataHigh, 2); temp = data[0] << 8; temp |= data[1]; temp >>= 2; Temperature = (((float)temp) / 32) - 50; }
/// <summary> /// Update the Temperature property. /// </summary> public void Update() { var temperatureData = _tmp102.ReadRegisters(0x00, 2); var sensorReading = 0; if (SensorResolution == Resolution.Resolution12Bits) { sensorReading = (temperatureData[0] << 4) | (temperatureData[1] >> 4); } else { sensorReading = (temperatureData[0] << 5) | (temperatureData[1] >> 3); } Temperature = (float)(sensorReading * 0.0625); }
/// <summary> /// Force a read of the current sensor values and update the Temperature /// and Pressure properties. /// </summary> public void Update() { // // Force the sensor to make a reading by setting the OST bit in Control // register 1 (see 7.17.1 of the datasheet). // Standby = false; // // Pause until both temperature and pressure readings are available. // while ((Status & 0x06) != 0x06) { Thread.Sleep(5); } Thread.Sleep(100); var data = _mpl3115a2.ReadRegisters(Registers.PressureMSB, 5); Pressure = DecodePresssure(data[0], data[1], data[2]); Temperature = DecodeTemperature(data[3], data[4]); }
/// <summary> /// Create a new MPL115A2 temperature and humidity sensor object. /// </summary> /// <param name="address">Sensor address (default to 0x60).</param> /// <param name="speed">Speed of the I2C interface (default to 100 KHz).</param> /// <param name="updateInterval">Number of milliseconds between samples (0 indicates polling to be used)</param> /// <param name="temperatureChangeNotificationThreshold">Changes in temperature greater than this value will trigger an event when updatePeriod > 0.</param> /// <param name="pressureChangedNotificationThreshold">Changes in pressure greater than this value will trigger an event when updatePeriod > 0.</param> public MPL115A2(byte address = 0x60, ushort speed = 100, ushort updateInterval = MinimumPollingPeriod, float temperatureChangeNotificationThreshold = 0.001F, float pressureChangedNotificationThreshold = 10.0F) { if ((speed < 10) || (speed > 1000)) { throw new ArgumentOutOfRangeException(nameof(speed), "Speed should be 10 KHz to 3,400 KHz."); } if (temperatureChangeNotificationThreshold < 0) { throw new ArgumentOutOfRangeException(nameof(temperatureChangeNotificationThreshold), "Temperature threshold should be >= 0"); } if (pressureChangedNotificationThreshold < 0) { throw new ArgumentOutOfRangeException(nameof(pressureChangedNotificationThreshold), "Pressure threshold should be >= 0"); } if ((updateInterval != 0) && (updateInterval < MinimumPollingPeriod)) { throw new ArgumentOutOfRangeException(nameof(updateInterval), "Update period should be 0 or >= than " + MinimumPollingPeriod); } TemperatureChangeNotificationThreshold = temperatureChangeNotificationThreshold; PressureChangeNotificationThreshold = pressureChangedNotificationThreshold; _updateInterval = updateInterval; var device = new I2cBus(address, speed); _mpl115a2 = device; // // Update the compensation data from the sensor. The location and format of the // compensation data can be found on pages 5 and 6 of the datasheet. // var data = _mpl115a2.ReadRegisters(Registers.A0MSB, 8); var a0 = (short)(ushort)((data[0] << 8) | data[1]); var b1 = (short)(ushort)((data[2] << 8) | data[3]); var b2 = (short)(ushort)((data[4] << 8) | data[5]); var c12 = (short)(ushort)(((data[6] << 8) | data[7]) >> 2); // // Convert the raw compensation coefficients from the sensor into the // doubleing point equivalents to speed up the calculations when readings // are made. // // Datasheet, section 3.1 // a0 is signed with 12 integer bits followed by 3 fractional bits so divide by 2^3 (8) // _coefficients.A0 = (double)a0 / 8; // // b1 is 2 integer bits followed by 7 fractional bits. The lower bits are all 0 // so the format is: // sign i1 I0 F12...F0 // // So we need to divide by 2^13 (8192) // _coefficients.B1 = (double)b1 / 8192; // // b2 is signed integer (1 bit) followed by 14 fractional bits so divide by 2^14 (16384). // _coefficients.B2 = (double)b2 / 16384; // // c12 is signed with no integer bits but padded with 9 zeroes: // sign 0.000 000 000 f12...f0 // // So we need to divide by 2^22 (4,194,304) - 13 doubleing point bits // plus 9 leading zeroes. // _coefficients.C12 = (double)c12 / 4194304; if (updateInterval > 0) { StartUpdating(); } else { Update(); } }
/// <summary> /// Display the registers. /// </summary> public void DisplayRegisters() { var data = _ds323x.ReadRegisters(0, 0x12); DebugInformation.DisplayRegisters(0, data); }