Commit f5eac720 authored by Maxime Robin's avatar Maxime Robin

affichage et selection capteur OK ; CLR pour arrêter mesure OK

parent 8c47718d
/*
* Copyright (c) 2016, Sensirion AG <andreas.brauchli@sensirion.com>
* Copyright (c) 2015-2016, Johannes Winkelmann <jw@smts.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <inttypes.h>
#include <Wire.h>
#include <Arduino.h>
#include "SHTSensor.h"
//
// class SHTSensorDriver
//
SHTSensorDriver::~SHTSensorDriver()
{
}
bool SHTSensorDriver::readSample()
{
return false;
}
//
// class SHTI2cSensor
//
const uint8_t SHTI2cSensor::CMD_SIZE = 2;
const uint8_t SHTI2cSensor::EXPECTED_DATA_SIZE = 6;
const uint8_t SHTI2cSensor::MAX_I2C_READ_TRIES = 5;
bool SHTI2cSensor::readFromI2c(uint8_t i2cAddress,
const uint8_t *i2cCommand,
uint8_t commandLength, uint8_t *data,
uint8_t dataLength)
{
Wire.beginTransmission(i2cAddress);
for (int i = 0; i < commandLength; ++i) {
if (Wire.write(i2cCommand[i]) != 1) {
return false;
}
}
if (Wire.endTransmission(false) != 0) {
return false;
}
Wire.requestFrom(i2cAddress, dataLength);
// there should be no reason for this to not be ready, since we're using clock
// stretching mode, but just in case we'll try a few times
uint8_t tries = 1;
while (Wire.available() < dataLength) {
delay(1);
if (tries++ >= MAX_I2C_READ_TRIES) {
return false;
}
}
for (int i = 0; i < dataLength; ++i) {
data[i] = Wire.read();
}
return true;
}
uint8_t SHTI2cSensor::crc8(const uint8_t *data, uint8_t len)
{
// adapted from SHT21 sample code from
// http://www.sensirion.com/en/products/humidity-temperature/download-center/
uint8_t crc = 0xff;
uint8_t byteCtr;
for (byteCtr = 0; byteCtr < len; ++byteCtr) {
crc ^= data[byteCtr];
for (uint8_t bit = 8; bit > 0; --bit) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc = (crc << 1);
}
}
}
return crc;
}
bool SHTI2cSensor::readSample()
{
uint8_t data[EXPECTED_DATA_SIZE];
uint8_t cmd[CMD_SIZE];
cmd[0] = mI2cCommand >> 8;
cmd[1] = mI2cCommand & 0xff;
if (!readFromI2c(mI2cAddress, cmd, CMD_SIZE, data,
EXPECTED_DATA_SIZE)) {
return false;
}
// -- Important: assuming each 2 byte of data is followed by 1 byte of CRC
// check CRC for both RH and T
if (crc8(&data[0], 2) != data[2] || crc8(&data[3], 2) != data[5]) {
return false;
}
// convert to Temperature/Humidity
uint16_t val;
val = (data[0] << 8) + data[1];
mTemperature = mA + mB * (val / mC);
val = (data[3] << 8) + data[4];
mHumidity = mX * (val / mY);
return true;
}
//
// class SHTC1Sensor
//
class SHTC1Sensor : public SHTI2cSensor
{
public:
SHTC1Sensor()
// Using clock stretching, high precision, T first
: SHTI2cSensor(0x70, 0x7ca2, -45, 175, 65535, 100, 65535)
{
}
};
//
// class SHT3xSensor
//
class SHT3xSensor : public SHTI2cSensor
{
private:
static const uint16_t SHT3X_ACCURACY_HIGH = 0x2c06;
static const uint16_t SHT3X_ACCURACY_MEDIUM = 0x2c0d;
static const uint16_t SHT3X_ACCURACY_LOW = 0x2c10;
public:
static const uint8_t SHT3X_I2C_ADDRESS_44 = 0x44;
static const uint8_t SHT3X_I2C_ADDRESS_45 = 0x45;
SHT3xSensor(uint8_t i2cAddress = SHT3X_I2C_ADDRESS_44)
: SHTI2cSensor(i2cAddress, SHT3X_ACCURACY_HIGH,
-45, 175, 65535, 100, 65535)
{
}
virtual bool setAccuracy(SHTSensor::SHTAccuracy newAccuracy)
{
switch (newAccuracy) {
case SHTSensor::SHT_ACCURACY_HIGH:
mI2cCommand = SHT3X_ACCURACY_HIGH;
break;
case SHTSensor::SHT_ACCURACY_MEDIUM:
mI2cCommand = SHT3X_ACCURACY_MEDIUM;
break;
case SHTSensor::SHT_ACCURACY_LOW:
mI2cCommand = SHT3X_ACCURACY_LOW;
break;
default:
return false;
}
return true;
}
};
//
// class SHT3xAnalogSensor
//
float SHT3xAnalogSensor::readHumidity()
{
float max_adc = (float)((1 << mReadResolutionBits) - 1);
return -12.5f + 125 * (analogRead(mHumidityAdcPin) / max_adc);
}
float SHT3xAnalogSensor::readTemperature()
{
float max_adc = (float)((1 << mReadResolutionBits) - 1);
return -66.875f + 218.75f * (analogRead(mTemperatureAdcPin) / max_adc);
}
//
// class SHTSensor
//
const SHTSensor::SHTSensorType SHTSensor::AUTO_DETECT_SENSORS[] = {
SHT3X,
SHT3X_ALT,
SHTC1
};
const float SHTSensor::TEMPERATURE_INVALID = NAN;
const float SHTSensor::HUMIDITY_INVALID = NAN;
bool SHTSensor::init()
{
if (mSensor != NULL) {
cleanup();
}
switch(mSensorType) {
case SHT3X:
mSensor = new SHT3xSensor();
break;
case SHT3X_ALT:
mSensor = new SHT3xSensor(SHT3xSensor::SHT3X_I2C_ADDRESS_45);
break;
case SHTW1:
case SHTW2:
case SHTC1:
mSensor = new SHTC1Sensor();
break;
case AUTO_DETECT:
{
bool detected = false;
for (unsigned int i = 0;
i < sizeof(AUTO_DETECT_SENSORS) / sizeof(AUTO_DETECT_SENSORS[0]);
++i) {
mSensorType = AUTO_DETECT_SENSORS[i];
if (init() && readSample()) {
detected = true;
break;
}
}
if (!detected) {
cleanup();
}
break;
}
}
return (mSensor != NULL);
}
bool SHTSensor::readSample()
{
if (!mSensor || !mSensor->readSample())
return false;
mTemperature = mSensor->mTemperature;
mHumidity = mSensor->mHumidity;
return true;
}
bool SHTSensor::setAccuracy(SHTAccuracy newAccuracy)
{
if (!mSensor)
return false;
return mSensor->setAccuracy(newAccuracy);
}
void SHTSensor::cleanup()
{
if (mSensor) {
delete mSensor;
mSensor = NULL;
}
}
/*
* Copyright (c) 2016, Sensirion AG <andreas.brauchli@sensirion.com>
* Copyright (c) 2015-2016, Johannes Winkelmann <jw@smts.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHTSENSOR_H
#define SHTSENSOR_H
#include <inttypes.h>
// Forward declaration
class SHTSensorDriver;
/**
* Official interface for Sensirion SHT Sensors
*/
class SHTSensor
{
public:
/**
* Enum of the supported Digital Sensirion SHT Sensors.
* For analog sensors, see SHT3xAnalogSensor.
* Using the special AUTO_DETECT sensor causes all i2c sensors to be
* probed. The first matching sensor will then be used.
*/
enum SHTSensorType {
/** Automatically detect the sensor type (only i2c sensors listed above) */
AUTO_DETECT,
// i2c Sensors:
/** SHT3x-DIS with ADDR (sensor pin 2) connected to VSS (default) */
SHT3X,
/** SHT3x-DIS with ADDR (sensor pin 2) connected to VDD */
SHT3X_ALT,
SHTC1,
SHTW1,
SHTW2
};
/**
* Accuracy setting of measurement.
* Not all sensors support changing the sampling accuracy.
*/
enum SHTAccuracy {
/** Highest repeatability at the cost of slower measurement */
SHT_ACCURACY_HIGH,
/** Balanced repeatability and speed of measurement */
SHT_ACCURACY_MEDIUM,
/** Fastest measurement but lowest repeatability */
SHT_ACCURACY_LOW
};
/** Value reported by getHumidity() when the sensor is not initialized */
static const float HUMIDITY_INVALID;
/** Value reported by getTemperature() when the sensor is not initialized */
static const float TEMPERATURE_INVALID;
/**
* Auto-detectable sensor types.
* Note that the SHTW1 and SHTW2 share exactly the same driver as the SHTC1
* and are thus not listed individually.
*/
static const SHTSensorType AUTO_DETECT_SENSORS[];
/**
* Instantiate a new SHTSensor
* By default, the i2c bus is queried for known SHT Sensors. To address
* a specific sensor, set the `sensorType'.
*/
SHTSensor(SHTSensorType sensorType = AUTO_DETECT)
: mSensorType(sensorType),
mSensor(NULL),
mTemperature(SHTSensor::TEMPERATURE_INVALID),
mHumidity(SHTSensor::HUMIDITY_INVALID)
{
}
virtual ~SHTSensor() {
cleanup();
}
/**
* Initialize the sensor driver
* To read out the sensor use readSample(), followed by getTemperature() and
* getHumidity() to retrieve the values from the sample
*/
bool init();
/**
* Read new values from the sensor
* After the call, use getTemperature() and getHumidity() to retrieve the
* values
* Returns true if the sample was read and the values are cached
*/
bool readSample();
/**
* Get the relative humidity in percent read from the last sample
* Use readSample() to trigger a new sensor reading
*/
float getHumidity() const {
return mHumidity;
}
/**
* Get the humidity in percent read from the last sample
* Use readSample() to trigger a new sensor reading
*/
float getTemperature() const {
return mTemperature;
}
/**
* Change the sensor accurancy, if supported by the sensor
* Returns true if the accuracy was changed
*/
bool setAccuracy(SHTAccuracy newAccuracy);
private:
void cleanup();
SHTSensorType mSensorType;
SHTSensorDriver *mSensor;
float mTemperature;
float mHumidity;
};
/** Abstract class for a digital SHT Sensor driver */
class SHTSensorDriver
{
public:
virtual ~SHTSensorDriver() = 0;
/**
* Set the sensor accuracy.
* Returns false if the sensor does not support changing the accuracy
*/
virtual bool setAccuracy(SHTSensor::SHTAccuracy newAccuracy) {
return false;
}
/** Returns true if the next sample was read and the values are cached */
virtual bool readSample();
/**
* Get the relative humidity in percent read from the last sample
* Use readSample() to trigger a new sensor reading
*/
float getHumidity() const {
return mHumidity;
}
/**
* Get the humidity in percent read from the last sample
* Use readSample() to trigger a new sensor reading
*/
float getTemperature() const {
return mTemperature;
}
float mTemperature;
float mHumidity;
};
/** Base class for i2c SHT Sensor drivers */
class SHTI2cSensor : public SHTSensorDriver {
public:
/** Size of i2c commands to send */
static const uint8_t CMD_SIZE;
/** Size of i2c replies to expect */
static const uint8_t EXPECTED_DATA_SIZE;
/**
* Constructor for i2c SHT Sensors
* Takes the `i2cAddress' to read, the `i2cCommand' issues when sampling
* the sensor and the values `a', `b', `c' to convert the fixed-point
* temperature value received by the sensor to a floating point value using
* the formula: temperature = a + b * (rawTemperature / c)
* and the values `x' and `y' to convert the fixed-point humidity value
* received by the sensor to a floating point value using the formula:
* humidity = x * (rawHumidity / y)
*/
SHTI2cSensor(uint8_t i2cAddress, uint16_t i2cCommand,
float a, float b, float c,
float x, float y)
: mI2cAddress(i2cAddress), mI2cCommand(i2cCommand),
mA(a), mB(b), mC(c), mX(x), mY(y)
{
}
virtual ~SHTI2cSensor()
{
}
virtual bool readSample();
uint8_t mI2cAddress;
uint16_t mI2cCommand;
float mA;
float mB;
float mC;
float mX;
float mY;
private:
static const uint8_t MAX_I2C_READ_TRIES;
static uint8_t crc8(const uint8_t *data, uint8_t len);
static bool readFromI2c(uint8_t i2cAddress,
const uint8_t *i2cCommand,
uint8_t commandLength, uint8_t *data,
uint8_t dataLength);
};
class SHT3xAnalogSensor
{
public:
/**
* Instantiate a new Sensirion SHT3x Analog sensor driver instance.
* The required paramters are `humidityPin` and `temperaturePin`
* An optional `readResolutionBits' can be set since the Arduino/Genuino Zero
* support 12bit precision analog readings. By default, 10 bit precision is
* used.
*
* Example usage:
* SHT3xAnalogSensor sht3xAnalog(HUMIDITY_PIN, TEMPERATURE_PIN);
* float humidity = sht.readHumidity();
* float temperature = sht.readTemperature();
*/
SHT3xAnalogSensor(uint8_t humidityPin, uint8_t temperaturePin,
uint8_t readResolutionBits = 10)
: mHumidityAdcPin(humidityPin), mTemperatureAdcPin(temperaturePin),
mReadResolutionBits(readResolutionBits)
{
}
virtual ~SHT3xAnalogSensor()
{
}
float readHumidity();
float readTemperature();
uint8_t mHumidityAdcPin;
uint8_t mTemperatureAdcPin;
uint8_t mReadResolutionBits;
};
#endif /* SHTSENSOR_H */
...@@ -72,25 +72,33 @@ I2CEEPROM i2c_eeprom(CHIP_ADDRESS); // Create I2C EEPROM instance ...@@ -72,25 +72,33 @@ I2CEEPROM i2c_eeprom(CHIP_ADDRESS); // Create I2C EEPROM instance
unsigned int current_adress = 0; unsigned int current_adress = 0;
short int capteurEnTest = 100; short int capteurEnTest = 100;
unsigned short int coeffCalibrationRadiometres = 0; float coeffCalibrationRadiometres = 0;
void saisieCoeffCalibration() { void saisieCoeffCalibration() {
Serial.println("Saisie coeff"); Serial.println("Saisie coeff");
char CursorCoeff=0; char CursorCoeff=0;
lcd.setCursor(0,1); lcd.print("Coeff de calibration "); // BONUS : * pour la virgule, # pour valider. '); lcd.clear();
for (char i=3; i>0; i--) { lcd.setCursor(0,0); lcd.print("Coeff calibration"); // BONUS : * pour la virgule, # pour valider. ');
key=kpd.get_key(); lcd.setCursor(0,1); lcd.print("c=");
if(key != "\0") { for (char i=3; i>=0; i--) {
Serial.println(key); key='\0';
lcd.setCursor(0,0); lcd.print("c="); while(key == '\0') {key=kpd.get_key(); } // on attend qu'une touche soit appuyée
CursorCoeff = (CursorCoeff+1)%4;
lcd.setCursor(3+CursorCoeff,0); // on se place juste après le "=" Serial.println(key);
lcd.print(key); lcd.setCursor(0,1); lcd.print("c=");
coeffCalibrationRadiometres=(key-48)*10^(i-2); // Dizaines puis sens des puissances décroissantes lcd.setCursor(3+CursorCoeff,1); // on se place juste après le "="
// 10^(1) --> 10^(-2) if (i==1) { lcd.print("."); CursorCoeff++; } // affichage du point à l'ecriture du coeff
Serial.println(coeffCalibrationRadiometres); lcd.print(key);
} coeffCalibrationRadiometres+=( ((int)key)-48 )*pow(10,i-2); // Dizaines puis sens des puissances décroissantes
// 10^(1) --> 10^(-2)
CursorCoeff++; // deplacement curseur
Serial.println(coeffCalibrationRadiometres);
} }
delay(1000);
lcd.setCursor(0,0); lcd.print("Coeff final : "); //nettoyage ligne supérieure
lcd.setCursor(0,1); lcd.print("c= "); lcd.print(coeffCalibrationRadiometres);
delay(2000);
} }
void instructions() { void instructions() {
...@@ -165,6 +173,8 @@ void configurationAmpli() { ...@@ -165,6 +173,8 @@ void configurationAmpli() {
* ============================================ * ============================================
*/ */
void mesureAmpli() { void mesureAmpli() {
lcd.clear();
Serial.println("Entree mesure ampli"); Serial.println("Entree mesure ampli");
long voltage; long voltage;
MCP.NewConversion(); // New conversion is initiated MCP.NewConversion(); // New conversion is initiated
...@@ -184,6 +194,7 @@ void mesureAmpli() { ...@@ -184,6 +194,7 @@ void mesureAmpli() {
} }
void mesureThermocouple() { void mesureThermocouple() {
lcd.clear();
Serial.println("Entree mesure thermocouple"); Serial.println("Entree mesure thermocouple");
lcd.setCursor(0,0); lcd.print("CJT="); lcd.setCursor(0,0); lcd.print("CJT=");
lcd.setCursor(4,0); lcd.print(maxThermocouple.readCJTemperature()); lcd.setCursor(4,0); lcd.print(maxThermocouple.readCJTemperature());
...@@ -194,6 +205,7 @@ void mesureThermocouple() { ...@@ -194,6 +205,7 @@ void mesureThermocouple() {
} }
void mesurePT100() { void mesurePT100() {
lcd.clear();
Serial.println("Entree mesure PT100"); Serial.println("Entree mesure PT100");
maxPT100.read_all( ); maxPT100.read_all( );
...@@ -210,6 +222,7 @@ unsigned short int compteurImpulsions=0; ...@@ -210,6 +222,7 @@ unsigned short int compteurImpulsions=0;
void incrementCompteurAnemometre() { void incrementCompteurAnemometre() {