Réorganisation de la bibliothèque MeasureUnit
This commit is contained in:
parent
44e40b8ab3
commit
ebba78c49b
@ -1,43 +0,0 @@
|
||||
#include "Adc.h"
|
||||
|
||||
Adc::Adc() : _lastChannel(0), _adcSetting(0,0), _state(IDLING), _sampledValue(0), _numOfSamples(0), _elapsedTime(0)
|
||||
{
|
||||
//Serial.println("Adc constructor called");
|
||||
}
|
||||
|
||||
Adc::~Adc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Adc::setAdcSetting(AdcSetting adcSetting)
|
||||
{
|
||||
_adcSetting = adcSetting;
|
||||
}
|
||||
|
||||
AdcSetting Adc::getAdcSetting()
|
||||
{
|
||||
return _adcSetting;
|
||||
}
|
||||
|
||||
boolean Adc::isSampleReady()
|
||||
{
|
||||
return _state == RESULT_READY;
|
||||
}
|
||||
|
||||
double Adc::getQuantum()
|
||||
{
|
||||
return _adcSetting.getQuantum();
|
||||
}
|
||||
|
||||
double Adc::getSampleValue()
|
||||
{
|
||||
double ret(0);
|
||||
if(_state == RESULT_READY)
|
||||
{
|
||||
ret = _sampledValue;
|
||||
_state = IDLING;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
#ifndef ADC_H
|
||||
#define ADC_H
|
||||
#include "AdcSetting.h"
|
||||
|
||||
class Adc
|
||||
{
|
||||
public:
|
||||
virtual ~Adc() = 0;
|
||||
|
||||
virtual void begin() = 0;
|
||||
virtual double getQuantum();
|
||||
virtual double sampleValue(int16_t channel, boolean sgl = true) = 0;
|
||||
virtual double sampleValue() = 0;
|
||||
virtual double sampleVoltage(int16_t channel, boolean sgl = true) = 0;
|
||||
virtual double sampleVoltage() = 0;
|
||||
|
||||
//Async methods
|
||||
enum STATE {STARTED = 0, RESULT_READY, IDLING, SAMPLING};
|
||||
virtual void startSample(int16_t channel, boolean sgl = true) = 0;
|
||||
virtual void startSample() = 0;
|
||||
virtual double getSampleVoltage() = 0;
|
||||
|
||||
boolean isSampleReady();
|
||||
double getSampleValue();
|
||||
//End of async methods
|
||||
|
||||
void setAdcSetting(AdcSetting adcSetting);
|
||||
AdcSetting getAdcSetting();
|
||||
protected:
|
||||
Adc();
|
||||
|
||||
int16_t _lastChannel;
|
||||
AdcSetting _adcSetting;
|
||||
//Async part
|
||||
STATE _state;
|
||||
double _sampledValue;
|
||||
uint8_t _numOfSamples;
|
||||
unsigned long _elapsedTime;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //ADC_H
|
@ -1,19 +0,0 @@
|
||||
#include "AdcSetting.h"
|
||||
|
||||
AdcSetting::AdcSetting(double vref,
|
||||
uint8_t adcResolution,
|
||||
uint8_t measureIteration,
|
||||
uint16_t delayBetweenIteration) : _vref(vref), _adcResolution(adcResolution), _measureIteration(measureIteration), _delayBetweenIteration(delayBetweenIteration), _quantum(vref/(pow(2.0,(double) adcResolution)-1))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t AdcSetting::getMeasureIteration()
|
||||
{
|
||||
return _measureIteration;
|
||||
}
|
||||
|
||||
double AdcSetting::getQuantum()
|
||||
{
|
||||
return _quantum;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#ifndef ADCSETTING_H
|
||||
#define ADCSETTING_H
|
||||
#include <Arduino.h>
|
||||
#include <math.h>
|
||||
|
||||
class AdcSetting
|
||||
{
|
||||
public:
|
||||
AdcSetting(double vref, uint8_t adcResolution, uint8_t measureIteration = 5, uint16_t delayBetweenIteration = 5);
|
||||
~AdcSetting(){}
|
||||
|
||||
uint8_t getMeasureIteration();
|
||||
uint16_t getDelayBetweenIteration(){ return _delayBetweenIteration;}
|
||||
double getQuantum();
|
||||
double getVref(){return _vref;}
|
||||
protected:
|
||||
private:
|
||||
double _vref;
|
||||
uint8_t _adcResolution;
|
||||
double _quantum;
|
||||
uint8_t _measureIteration;
|
||||
uint16_t _delayBetweenIteration;
|
||||
};
|
||||
|
||||
#endif //ADCSETTING_H
|
@ -1,127 +0,0 @@
|
||||
#include "Ads1115.h"
|
||||
#define ADS_DEBUG
|
||||
|
||||
Ads1115::Ads1115() : ads1(0x48), ads2(0x49)
|
||||
{
|
||||
#ifdef ADS_DEBUG
|
||||
Serial.println("Ads1115 constructor called");
|
||||
#endif
|
||||
//We set the adcs up:
|
||||
ads1.setGain(GAIN_ONE);
|
||||
ads2.setGain(GAIN_ONE);
|
||||
}
|
||||
|
||||
Ads1115::~Ads1115()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Ads1115::begin()
|
||||
{
|
||||
#ifdef ADS_DEBUG
|
||||
Serial.println("Ads1115 : begin");
|
||||
#endif
|
||||
ads1.begin();
|
||||
ads2.begin();
|
||||
}
|
||||
|
||||
double Ads1115::getQuantum()
|
||||
{
|
||||
return 0.125;
|
||||
}
|
||||
|
||||
double Ads1115::sampleValue(int16_t channel, boolean sgl)
|
||||
{
|
||||
double total(0);
|
||||
for(int i(0); i < getAdcSetting().getMeasureIteration(); i++)
|
||||
{
|
||||
delay(getAdcSetting().getDelayBetweenIteration());
|
||||
total += getReading(channel, sgl);
|
||||
}
|
||||
|
||||
//We divide
|
||||
total /= (double)getAdcSetting().getMeasureIteration();
|
||||
|
||||
//We return
|
||||
return total;
|
||||
}
|
||||
|
||||
double Ads1115::sampleValue()
|
||||
{
|
||||
return sampleValue(-1);
|
||||
}
|
||||
|
||||
double Ads1115::sampleVoltage(int16_t channel, boolean sgl)
|
||||
{
|
||||
return sampleValue(channel, sgl)*0.125;
|
||||
}
|
||||
|
||||
double Ads1115::sampleVoltage()
|
||||
{
|
||||
return sampleValue()*0.125;
|
||||
}
|
||||
|
||||
uint16_t Ads1115::getReading(int16_t channel, boolean sgl)
|
||||
{
|
||||
int16_t chan(channel == -1 ? _lastChannel : channel);
|
||||
|
||||
_lastChannel = chan > 8 ? 0 : chan;
|
||||
|
||||
if(chan < 4)
|
||||
{
|
||||
return ads1.readADC_SingleEnded(chan);
|
||||
}
|
||||
else if(chan < 8)
|
||||
{
|
||||
return ads2.readADC_SingleEnded(chan - 4);
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
//Async part
|
||||
void Ads1115::startSample(int16_t channel, boolean sgl)
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case IDLING:
|
||||
_state = SAMPLING;
|
||||
_elapsedTime = millis();
|
||||
_sampledValue = 0.0;
|
||||
_numOfSamples = 0;
|
||||
//We set the last channel attribute
|
||||
if(channel != -1)
|
||||
{
|
||||
_lastChannel = channel > 8 ? _lastChannel : channel;
|
||||
}
|
||||
|
||||
break;
|
||||
case SAMPLING:
|
||||
//If enough time elapsed, we can sample a value again
|
||||
if(millis() - _elapsedTime > getAdcSetting().getDelayBetweenIteration())
|
||||
{
|
||||
_sampledValue += getReading(channel, sgl);
|
||||
_elapsedTime = millis();
|
||||
_numOfSamples ++;
|
||||
}
|
||||
|
||||
//All samples are done:
|
||||
if(_numOfSamples == getAdcSetting().getMeasureIteration())
|
||||
{
|
||||
_sampledValue /= (double)_numOfSamples;
|
||||
_sampledValue += channel > 3 ? 82.0 : 0.0;
|
||||
_state = RESULT_READY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Ads1115::startSample()
|
||||
{
|
||||
startSample(-1);
|
||||
}
|
||||
|
||||
double Ads1115::getSampleVoltage()
|
||||
{
|
||||
return getSampleValue() * 0.125;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef ADS1115_H
|
||||
#define ADS1115_H
|
||||
#include "Adc.h"
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_ADS1015.h>
|
||||
|
||||
class Ads1115 : public Adc
|
||||
{
|
||||
public:
|
||||
Ads1115();
|
||||
~Ads1115();
|
||||
|
||||
virtual void begin();
|
||||
virtual double getQuantum();
|
||||
virtual double sampleValue(int16_t channel, boolean sgl = true);
|
||||
virtual double sampleValue();
|
||||
virtual double sampleVoltage(int16_t channel, boolean sgl = true);
|
||||
virtual double sampleVoltage();
|
||||
|
||||
//Async methods
|
||||
virtual void startSample(int16_t channel, boolean sgl = true);
|
||||
virtual void startSample();
|
||||
virtual double getSampleVoltage();
|
||||
//End of async methods
|
||||
protected:
|
||||
private:
|
||||
uint16_t getReading(int16_t channel = -1, boolean sgl = true);
|
||||
Adafruit_ADS1115 ads1, ads2;
|
||||
};
|
||||
|
||||
#endif //ADS1115_H
|
@ -1,134 +0,0 @@
|
||||
#include "Ads1115V2.h"
|
||||
#define ADSV2_DEBUG
|
||||
|
||||
Ads1115V2::Ads1115V2() : ads1(ADS1115_ADDRESS_ADDR_GND), ads2(ADS1115_ADDRESS_ADDR_VDD)
|
||||
{
|
||||
#ifdef ADSV2_DEBUG
|
||||
Serial.println("Ads1115 constructor called");
|
||||
#endif
|
||||
}
|
||||
|
||||
Ads1115V2::~Ads1115V2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Ads1115V2::begin()
|
||||
{
|
||||
#ifdef ADSV2_DEBUG
|
||||
Serial.println("Ads1115V2 : begin");
|
||||
#endif
|
||||
Wire.begin();
|
||||
//We set the adcs up:
|
||||
ads1.initialize();
|
||||
ads2.initialize();
|
||||
ads1.setMode(ADS1115_MODE_SINGLESHOT);
|
||||
ads2.setMode(ADS1115_MODE_SINGLESHOT);
|
||||
ads1.setRate(ADS1115_RATE_250);
|
||||
ads2.setRate(ADS1115_RATE_250);
|
||||
ads1.setGain(ADS1115_PGA_4P096);
|
||||
ads2.setGain(ADS1115_PGA_4P096);
|
||||
}
|
||||
|
||||
double Ads1115V2::getQuantum()
|
||||
{
|
||||
return 0.125;
|
||||
}
|
||||
|
||||
double Ads1115V2::sampleValue(int16_t channel, boolean sgl)
|
||||
{
|
||||
double total(0);
|
||||
for(int i(0); i < getAdcSetting().getMeasureIteration(); i++)
|
||||
{
|
||||
delay(getAdcSetting().getDelayBetweenIteration());
|
||||
total += getReading(channel, sgl);
|
||||
}
|
||||
|
||||
//We divide
|
||||
total /= (double)getAdcSetting().getMeasureIteration();
|
||||
|
||||
//We return
|
||||
return total;
|
||||
}
|
||||
|
||||
double Ads1115V2::sampleValue()
|
||||
{
|
||||
return sampleValue(-1);
|
||||
}
|
||||
|
||||
double Ads1115V2::sampleVoltage(int16_t channel, boolean sgl)
|
||||
{
|
||||
return sampleValue(channel, sgl)*0.125;
|
||||
}
|
||||
|
||||
double Ads1115V2::sampleVoltage()
|
||||
{
|
||||
return sampleValue()*0.125;
|
||||
}
|
||||
|
||||
uint16_t Ads1115V2::getReading(int16_t channel, boolean sgl)
|
||||
{
|
||||
int16_t chan(channel == -1 ? _lastChannel : channel);
|
||||
|
||||
_lastChannel = chan > 8 ? 0 : chan;
|
||||
|
||||
if(chan < 4)
|
||||
{
|
||||
ads1.setMultiplexer(chan+4);
|
||||
return ads1.getConversion(true);
|
||||
}
|
||||
else if(chan < 8)
|
||||
{
|
||||
ads2.setMultiplexer(chan);
|
||||
return ads2.getConversion(true);
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
//Async part
|
||||
void Ads1115V2::startSample(int16_t channel, boolean sgl)
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case IDLING:
|
||||
_state = SAMPLING;
|
||||
_elapsedTime = millis();
|
||||
_sampledValue = 0.0;
|
||||
_numOfSamples = 0;
|
||||
//We set the last channel attribute
|
||||
if(channel != -1)
|
||||
{
|
||||
_lastChannel = channel > 8 ? _lastChannel : channel;
|
||||
}
|
||||
|
||||
break;
|
||||
case SAMPLING:
|
||||
//If enough time elapsed, we can sample a value again
|
||||
if(millis() - _elapsedTime > getAdcSetting().getDelayBetweenIteration())
|
||||
{
|
||||
_sampledValue += getReading(channel, sgl);
|
||||
_elapsedTime = millis();
|
||||
_numOfSamples ++;
|
||||
}
|
||||
|
||||
//All samples are done:
|
||||
if(_numOfSamples == getAdcSetting().getMeasureIteration())
|
||||
{
|
||||
_sampledValue /= (double)_numOfSamples;
|
||||
_sampledValue += channel > 3 ? 82.0 : 0.0;
|
||||
_state = RESULT_READY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Ads1115V2::startSample()
|
||||
{
|
||||
startSample(-1);
|
||||
}
|
||||
|
||||
double Ads1115V2::getSampleVoltage()
|
||||
{
|
||||
return getSampleValue() * 0.125;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef ADS1115V2_H
|
||||
#define ADS1115V2_H
|
||||
#include "Adc.h"
|
||||
#include <Wire.h>
|
||||
#include <ADS1115x.h>
|
||||
|
||||
class Ads1115V2 : public Adc
|
||||
{
|
||||
public:
|
||||
Ads1115V2();
|
||||
~Ads1115V2();
|
||||
|
||||
virtual void begin();
|
||||
virtual double getQuantum();
|
||||
virtual double sampleValue(int16_t channel, boolean sgl = true);
|
||||
virtual double sampleValue();
|
||||
virtual double sampleVoltage(int16_t channel, boolean sgl = true);
|
||||
virtual double sampleVoltage();
|
||||
|
||||
//Async methods
|
||||
virtual void startSample(int16_t channel, boolean sgl = true);
|
||||
virtual void startSample();
|
||||
virtual double getSampleVoltage();
|
||||
//End of async methods
|
||||
protected:
|
||||
private:
|
||||
uint16_t getReading(int16_t channel = -1, boolean sgl = true);
|
||||
ADS1115 ads1, ads2;
|
||||
};
|
||||
|
||||
#endif //ADS1115V2_H
|
@ -1,375 +0,0 @@
|
||||
#include "MeasureUnit.h"
|
||||
//#define DEBUG
|
||||
|
||||
MeasureUnit::MeasureUnit(uint8_t *analogInput,
|
||||
uint16_t thermistorCount,
|
||||
uint64_t precResistor,
|
||||
ThermistorSetting thermistorSetting,
|
||||
Adc &adc) : _analogInput(analogInput),
|
||||
_thermistorCount(thermistorCount),
|
||||
_precResistor(precResistor),
|
||||
_thermistorSetting(thermistorSetting),
|
||||
_adc(adc),
|
||||
_globalOffset(0),
|
||||
_error(OK),
|
||||
_state(IDLING),
|
||||
_channel(0),
|
||||
_offsetComputeIte(7),
|
||||
_offsetCounter(7),
|
||||
_courant(0.0),
|
||||
_tension(0.0),
|
||||
_triggerLevelOff(false)
|
||||
{
|
||||
//Allocation dynamique des différent tableaux
|
||||
_temperatures = (double*) calloc(_thermistorCount, sizeof(double));
|
||||
_rOffsetMap = (double*) calloc(_thermistorCount, sizeof(double));
|
||||
_resistanceMap = (double*) malloc(_thermistorCount * sizeof(double));
|
||||
_rOffsetBuffer = (double*) malloc(_thermistorCount * sizeof(double));
|
||||
|
||||
if(_temperatures == NULL || _rOffsetMap == NULL || _resistanceMap == NULL || _rOffsetBuffer == NULL)
|
||||
{
|
||||
_error = MALLOC_ERR;
|
||||
_temperatures != NULL ? free(_temperatures):(void)_temperatures;
|
||||
_rOffsetMap != NULL ? free(_rOffsetMap):(void)_rOffsetMap;
|
||||
_resistanceMap != NULL ? free(_resistanceMap):(void)_resistanceMap;
|
||||
_rOffsetBuffer != NULL ? free(_rOffsetBuffer):(void)_rOffsetBuffer;
|
||||
|
||||
_temperatures = NULL;
|
||||
_rOffsetMap = NULL;
|
||||
_resistanceMap = NULL;
|
||||
_rOffsetBuffer = NULL;
|
||||
}
|
||||
|
||||
_adc.begin();
|
||||
}
|
||||
|
||||
MeasureUnit::~MeasureUnit()
|
||||
{
|
||||
if(_error != MALLOC_ERR)
|
||||
{
|
||||
free(_temperatures);
|
||||
free(_rOffsetMap);
|
||||
free(_resistanceMap);
|
||||
free(_rOffsetBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void MeasureUnit::run()
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case MEASURING:
|
||||
_adc.startSample(_channel);
|
||||
|
||||
if(_channel == 0) //Calcule du courant
|
||||
{
|
||||
if(_adc.isSampleReady())
|
||||
{
|
||||
_tension = _adc.getSampleVoltage();
|
||||
_courant = _tension / (double) _precResistor;
|
||||
#ifdef DEBUG
|
||||
Serial.print("Tension prec : ");Serial.println(_tension);
|
||||
#endif
|
||||
_channel++;
|
||||
}
|
||||
}
|
||||
else //Calcule des niveaux de tensions
|
||||
{
|
||||
if(_adc.isSampleReady())
|
||||
{
|
||||
_resistanceMap[_channel-1] = _adc.getSampleVoltage();
|
||||
#ifdef DEBUG
|
||||
Serial.print("Tension thermistances : ");Serial.println(_resistanceMap[_channel-1]);
|
||||
#endif
|
||||
_channel++;
|
||||
}
|
||||
}
|
||||
|
||||
//Fin de la partie d'acquisition
|
||||
if(_channel == _thermistorCount)
|
||||
{
|
||||
_state = COMPUTING;
|
||||
_resistanceMap[_channel-1] = _adc.getAdcSetting().getVref();
|
||||
}
|
||||
break;
|
||||
case COMPUTING :
|
||||
//Ici nous calculons les temperatures
|
||||
for(int i(_thermistorCount-1); i > 0; i--)
|
||||
{
|
||||
//Calcule de delta :
|
||||
_resistanceMap[i] -= _resistanceMap[i-1];
|
||||
#ifdef DEBUG
|
||||
Serial.printf("Debug voltage delta : %u -> ",i);Serial.println(_resistanceMap[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Ne pas oublier de déduire la chute de tension de la resistance de precision pour la première thermistance
|
||||
_resistanceMap[0] -= _tension;
|
||||
#ifdef DEBUG
|
||||
Serial.printf("Debug voltage delta : 0 -> ");Serial.println(_resistanceMap[0]);
|
||||
#endif
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
//3) Nous en déduisons la résistance
|
||||
//Serial.print("Resistance ");Serial.print(i);Serial.print(" ");Serial.println(_resistanceMap[i]);
|
||||
_resistanceMap[i] /= _courant;
|
||||
//4) Nous en déduisons la temperature
|
||||
_temperatures[i] = computeTemperature(_thermistorSetting.getBeta(), _resistanceMap[i], _thermistorSetting.getRat25());
|
||||
|
||||
//On effectue un étalonnage
|
||||
if(_triggerLevelOff)
|
||||
{
|
||||
double averageTemp(0);
|
||||
//We reset the offset
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetMap[i] = 0;
|
||||
}
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
averageTemp += _temperatures[i];
|
||||
}
|
||||
|
||||
averageTemp /= (double)_thermistorCount;
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetMap[i] = averageTemp - _temperatures[i];
|
||||
}
|
||||
_triggerLevelOff = false;
|
||||
}
|
||||
|
||||
_temperatures[i] += _rOffsetMap[i] + _globalOffset;
|
||||
#ifdef DEBUG_TEMP
|
||||
Serial.print("Temperature ");Serial.print(i);Serial.print(" : ");Serial.println(_temperatures[i]);
|
||||
#endif
|
||||
}
|
||||
_state = MEASUREMENT_READY;
|
||||
break;
|
||||
}
|
||||
|
||||
if(_offsetCounter < _offsetComputeIte && isMeasurementReady())
|
||||
{
|
||||
//We reset the offset array
|
||||
if(_offsetCounter == 0)
|
||||
{
|
||||
Serial.printf("Initiating average \n");
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetBuffer[i] = 0;
|
||||
_rOffsetMap[i] = 0;
|
||||
}
|
||||
}
|
||||
else if(_offsetCounter == _offsetComputeIte-1)
|
||||
{
|
||||
double averageTemp(0);
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetBuffer[i] += _temperatures[i];
|
||||
}
|
||||
//We compute the average for each thermistor:
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetBuffer[i] /= _offsetCounter;
|
||||
averageTemp += _rOffsetBuffer[i];
|
||||
}
|
||||
|
||||
averageTemp /= _thermistorCount;
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetMap[i] = averageTemp - _rOffsetBuffer[i];
|
||||
}
|
||||
|
||||
Serial.println("Offset done");
|
||||
Serial.print("|");
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
if(i != 7)
|
||||
{
|
||||
Serial.print(" ");Serial.print(_rOffsetMap[i],2);Serial.print(" |");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(" ");Serial.print(_rOffsetMap[i],2);Serial.print(" |");
|
||||
}
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetBuffer[i] += _temperatures[i];
|
||||
}
|
||||
}
|
||||
|
||||
_offsetCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
void MeasureUnit::setOffsetIteration(uint8_t iteration)
|
||||
{
|
||||
_offsetComputeIte = iteration;
|
||||
_offsetCounter = iteration;
|
||||
}
|
||||
|
||||
void MeasureUnit::startOffsetComputing()
|
||||
{
|
||||
_offsetCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Methode permettant d'effectuer les mesures de température et de les récupérer
|
||||
*/
|
||||
double *MeasureUnit::getTemperatures()
|
||||
{
|
||||
double courant(0), rPrecTension(0);
|
||||
//1) Nous calculons le courant présent dans la branche grace à la résistance de précision
|
||||
#ifdef DEBUG
|
||||
Serial.println("-------------");
|
||||
#endif
|
||||
rPrecTension = _adc.sampleVoltage(0);
|
||||
#ifdef DEBUG
|
||||
Serial.println("-------------");
|
||||
Serial.print("R prec voltage mV : ");Serial.println(rPrecTension,6);
|
||||
#endif
|
||||
|
||||
courant = rPrecTension / (double) _precResistor;
|
||||
#ifdef DEBUG
|
||||
Serial.print("R prec current mA : ");Serial.println(courant,6);
|
||||
#endif
|
||||
|
||||
|
||||
//2) Nous calculons le delta de tensions pour chaque thermistances
|
||||
for(int i(1); i < _thermistorCount; i++)
|
||||
{
|
||||
_resistanceMap[i-1] = _adc.sampleVoltage(_analogInput[i]);
|
||||
#ifdef DEBUG
|
||||
Serial.print("Voltage steps ");Serial.print(i-1);Serial.print(" : ");Serial.println(_resistanceMap[i-1]);
|
||||
#endif
|
||||
}
|
||||
_resistanceMap[7] = _adc.getAdcSetting().getVref();
|
||||
#ifdef DEBUG
|
||||
Serial.print("Voltage steps 7 : ");Serial.println(_resistanceMap[7]);
|
||||
#endif
|
||||
|
||||
for(int i(_thermistorCount-1); i > 0; i--)
|
||||
{
|
||||
//Calcule de delta :
|
||||
_resistanceMap[i] -= _resistanceMap[i-1];
|
||||
#ifdef DEBUG
|
||||
Serial.print("Debug voltage delta : ");Serial.println(_resistanceMap[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Ne pas oublier de déduire la chute de tension de la resistance de precision pour la première thermistance
|
||||
_resistanceMap[0] -= rPrecTension;
|
||||
Serial.printf("Debug voltage delta : 0 -> ");Serial.println(_resistanceMap[0]);
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
//3) Nous en déduisons la résistance
|
||||
//Serial.print("Resistance ");Serial.print(i);Serial.print(" ");Serial.println(_resistanceMap[i]);
|
||||
_resistanceMap[i] /= courant;
|
||||
//4) Nous en déduisons la temperature
|
||||
_temperatures[i] = computeTemperature(_thermistorSetting.getBeta(), _resistanceMap[i], _thermistorSetting.getRat25());
|
||||
_temperatures[i] += _rOffsetMap[i] + _globalOffset;
|
||||
#ifdef DEBUG_TEMP
|
||||
Serial.print("Temperature ");Serial.print(i);Serial.print(" : ");Serial.println(_temperatures[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
return _temperatures;
|
||||
}
|
||||
|
||||
double MeasureUnit::computeTemperature(double beta, double resistance, double rAt25)
|
||||
{
|
||||
return (((25.0+273.15) * beta) / (beta + (25.0+273.15)*log(resistance / rAt25))) - 273.15;
|
||||
}
|
||||
|
||||
void MeasureUnit::setGlobalTempOffset(double offset)
|
||||
{
|
||||
_globalOffset = offset;
|
||||
}
|
||||
|
||||
double MeasureUnit::getGlobalTempOffset()
|
||||
{
|
||||
return _globalOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cette méthode permet de calibrer toutes les temperatures en faisans la moyenne et appliquant un offset individuel
|
||||
*/
|
||||
void MeasureUnit::levelTemperaturesOff()
|
||||
{
|
||||
double averageTemp(0);
|
||||
//We reset the offset
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetMap[i] = 0;
|
||||
}
|
||||
|
||||
getTemperatures();
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
averageTemp += _temperatures[i];
|
||||
}
|
||||
|
||||
averageTemp /= _thermistorCount;
|
||||
|
||||
for(int i(0); i < _thermistorCount; i++)
|
||||
{
|
||||
_rOffsetMap[i] = averageTemp - _temperatures[i];
|
||||
}
|
||||
}
|
||||
|
||||
double *MeasureUnit::getROffsetMap()
|
||||
{
|
||||
return _rOffsetMap;
|
||||
}
|
||||
|
||||
boolean MeasureUnit::startTemperatureMeasurement()
|
||||
{
|
||||
|
||||
if(_state == IDLING)
|
||||
{
|
||||
_state = MEASURING;
|
||||
_channel = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MeasureUnit::levelAsyncTemperaturesOff()
|
||||
{
|
||||
_triggerLevelOff = true;
|
||||
}
|
||||
|
||||
boolean MeasureUnit::isMeasurementReady()
|
||||
{
|
||||
return _state == MEASUREMENT_READY;
|
||||
}
|
||||
|
||||
double *MeasureUnit::getAsyncTemperatures()
|
||||
{
|
||||
double *p(NULL);
|
||||
|
||||
if(_state == MEASUREMENT_READY)
|
||||
{
|
||||
p = _temperatures;
|
||||
_state = IDLING;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void MeasureUnit::init()
|
||||
{
|
||||
Serial.println(computeTemperature(3380, 18000, 10000));
|
||||
Serial.println(computeTemperature(3380, 11700, 10000));
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#ifndef MEASUREUNIT_H
|
||||
#define MEASUREUNIT_H
|
||||
#include "Ads1115.h"
|
||||
#include "ThermistorSetting.h"
|
||||
|
||||
//#define DEBUG_TEMP
|
||||
|
||||
class MeasureUnit
|
||||
{
|
||||
public:
|
||||
enum ERROR {OK = 0, MALLOC_ERR = 1};
|
||||
MeasureUnit(uint8_t *analogInput, uint16_t thermistorCount, uint64_t precResistor, ThermistorSetting thermistorSetting, Adc &adc);
|
||||
~MeasureUnit();
|
||||
void init();
|
||||
void run();
|
||||
void startOffsetComputing();
|
||||
void setOffsetIteration(uint8_t iteration);
|
||||
void setGlobalTempOffset(double offset);
|
||||
void levelTemperaturesOff();
|
||||
double getGlobalTempOffset();
|
||||
double *getTemperatures();
|
||||
double *getROffsetMap();
|
||||
|
||||
//Async methods
|
||||
enum STATE {IDLING, MEASURING, COMPUTING, MEASUREMENT_READY};
|
||||
boolean startTemperatureMeasurement();
|
||||
boolean isMeasurementReady();
|
||||
double *getAsyncTemperatures();
|
||||
void levelAsyncTemperaturesOff();
|
||||
//End of assync methods
|
||||
|
||||
ERROR getError(){return _error;}
|
||||
|
||||
protected:
|
||||
private:
|
||||
double computeTemperature(double beta, double resistance, double rAt25);
|
||||
|
||||
double _globalOffset; //Correspond à l'offset global nécessaire afin d'avoir une température qui corresponde à la réalité
|
||||
double *_temperatures; //Tableau contenant toutes les températures
|
||||
double *_rOffsetMap,*_rOffsetBuffer; //Tableau qui contient les offsets individuels pour chaque thermistance
|
||||
double *_resistanceMap; //Tableau qui contient les resistances associées aux thermistances (pour debug seulement)
|
||||
uint8_t *_analogInput; //Pointeur qui garde l'adresse du tableau contenant le nom des entrées analogiques
|
||||
uint16_t _thermistorCount;
|
||||
uint64_t _precResistor;
|
||||
ERROR _error;
|
||||
|
||||
Adc &_adc;
|
||||
ThermistorSetting _thermistorSetting;
|
||||
|
||||
//Async part
|
||||
STATE _state;
|
||||
uint8_t _channel, _offsetComputeIte,_offsetCounter;
|
||||
double _courant, _tension;
|
||||
boolean _triggerLevelOff; //Attribut permettant de savoir si un étalonnage a été demandé
|
||||
};
|
||||
|
||||
#endif //MEASUREUNIT_H
|
@ -1,205 +0,0 @@
|
||||
/**
|
||||
* Cet exemple correspond à l'application de test de la bibliothèque MeasureUnit qui
|
||||
* permet de calculer la température qui est fonction de la résistance d'une matrice de thermistance
|
||||
*
|
||||
* Anatole SCHRAMM-HENRY
|
||||
* 17/12/2019
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <WiFi.h>
|
||||
#include <RTClib.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include "MeasureUnit.h"
|
||||
#include "PayloadFormatter.h"
|
||||
#include "Ads1115.h"
|
||||
#include "LoRaRadio.h"
|
||||
|
||||
#define RADIO_ENABLED
|
||||
#define PUSH_BUTTON 0
|
||||
|
||||
uint8_t analogInput[] = {0,1,2,3,4,5,6,7};
|
||||
double *tempArray = NULL;
|
||||
|
||||
/*
|
||||
* Liste des offsets trouvés
|
||||
* | -0.49 | 0.36 | -0.29 | 0.38 | 0.44 | -0.35 | -0.21 | 0.14 |
|
||||
* | -0.72 | 0.07 | -0.52 | -0.01 | 2.38 | -0.65 | -0.44 | -0.11 |
|
||||
* | -0.99 | -0.06 | -0.74 | 2.24 | 0.73 | -0.86 | -0.68 | 0.35 |
|
||||
|
||||
*/
|
||||
|
||||
void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data)
|
||||
{
|
||||
Serial.println("Downlink received : ");
|
||||
for(uint8_t i(0); i < length; i++)
|
||||
{
|
||||
Serial.print(data[dataBeg + i],HEX);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
//Action en fonction de l'octet de commande
|
||||
switch(data[0])
|
||||
{
|
||||
case 0x01://Mise à jour de l'heure
|
||||
//Octets suivants:
|
||||
//2 jour 3 mois 4 année 5 heures 6 minutes
|
||||
if(length == 6)
|
||||
{
|
||||
Serial.printf("dd: %u, m: %u, yyyy: %d, hh: %u, mm: %u\n", data[2], data[3], data[4]+2000, data[5], data[6]);
|
||||
}
|
||||
else
|
||||
Serial.println("Action réglage RTC : paramètres insuffisants");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Action inconnnue");
|
||||
}
|
||||
}
|
||||
|
||||
//Objet de calcule de la temperature
|
||||
//ThermistorSetting thermistorSetting(3380, 10000);
|
||||
ThermistorSetting thermistorSetting(3650, 470);
|
||||
//AdcSetting adcSetting(3300.0, 12, 310, 3);
|
||||
AdcSetting adcSetting(3320, 15, 6, 10);
|
||||
Ads1115 adc;
|
||||
MeasureUnit measureUnit(analogInput, 8, 990, thermistorSetting, adc);
|
||||
//MeasureUnit measureUnit(analogInput, 8, 99, thermistorSetting, adc);
|
||||
//Objet de création des trames LoRa
|
||||
PayloadFormatter payloadFormatter(2,4);
|
||||
|
||||
RTC_DS3231 rtc;
|
||||
DateTime payloadDate;
|
||||
TwoWire sc(1);
|
||||
Adafruit_SSD1306 display(128,64,&sc, 16);
|
||||
|
||||
boolean data(false);
|
||||
uint8_t *payload(NULL), _timeCounter(0), size(0), _channel(0);
|
||||
boolean calibrer(false);
|
||||
unsigned long _time(0);
|
||||
/*
|
||||
* Radio Part
|
||||
*/
|
||||
void os_getArtEui (u1_t* buf) { }
|
||||
void os_getDevEui (u1_t* buf) { }
|
||||
void os_getDevKey (u1_t* buf) { }
|
||||
|
||||
static u1_t NWKSKEY[16] = { 0x1F, 0x9E, 0xE2, 0x7A, 0xC8, 0xBA, 0xE8, 0xEA, 0xF5, 0xC2, 0x5E, 0x47, 0x5D, 0xE0, 0x77, 0x55 };
|
||||
static u1_t APPSKEY[16] = { 0x3B, 0x89, 0x86, 0x96, 0xBB, 0xAA, 0x38, 0x1E, 0x1F, 0xC4, 0xAD, 0x03, 0xEF, 0x3F, 0x56, 0x12 };
|
||||
static u4_t DEVADDR = 0x260113D3;//0x03FF0001 ; // <-- Change this address for every node!
|
||||
|
||||
u1_t dio[3] = {26,33,32};
|
||||
PinMap pinMap(18, LMIC_UNUSED_PIN, 14, dio);
|
||||
LoRaRadio radio(pinMap);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
Serial.println("Start setup");
|
||||
WiFi.mode(WIFI_OFF);
|
||||
pinMode(PUSH_BUTTON, INPUT);
|
||||
//Partie concernant l'initialisation de la radio
|
||||
#ifdef RADIO_ENABLED
|
||||
radio.init();
|
||||
radio.setTTNSession(0x1, DEVADDR, NWKSKEY, APPSKEY);
|
||||
radio.setRadioEUChannels();
|
||||
/*
|
||||
* La directive setMCUClockError() permet de laisser une fenêtre plus grande pour le slot de
|
||||
* réception (Downlink). En effet ce slot doit durer 2 secondes et il peut durer moins en raison
|
||||
* d'imprécisions d'horloge.
|
||||
*/
|
||||
radio.setMCUClockError();
|
||||
radio.setDownlinkHandler(&(downlinkHandler));
|
||||
#endif
|
||||
//Adc init
|
||||
adc.setAdcSetting(adcSetting);
|
||||
//measureUnit.setGlobalTempOffset(-17);
|
||||
_time = millis();
|
||||
|
||||
if(rtc.begin())Serial.println("RTC Ok!");
|
||||
else Serial.println("RTC Fail!");
|
||||
sc.begin(4, 15);
|
||||
if(display.begin(SSD1306_SWITCHCAPVCC,0x3C))
|
||||
{
|
||||
Serial.println("SCREEN Ok!");
|
||||
display.clearDisplay();
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,15);
|
||||
display.setTextSize(2);
|
||||
display.print("LES ALEAS DU DIRECT");
|
||||
display.display();
|
||||
}
|
||||
else Serial.println("SCREEN Fail!");
|
||||
|
||||
display.startscrollleft(0,16);
|
||||
Serial.println("End setup");
|
||||
measureUnit.init();
|
||||
Serial.println("| T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 |");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Version asynchrone :
|
||||
measureUnit.startTemperatureMeasurement();
|
||||
|
||||
//On peut tester si la conversion est terminée avec :
|
||||
//if(measureUnit.isMeasurementReady())
|
||||
|
||||
//measureUnit.getAsyncTemperatures() renvoie NULL si la recupération de la température n'est pas terminée
|
||||
tempArray = measureUnit.getAsyncTemperatures();
|
||||
|
||||
if(tempArray != NULL)
|
||||
{
|
||||
Serial.print("|");
|
||||
for(int i(0); i < 8; i++)
|
||||
{
|
||||
if(i != 7)
|
||||
{
|
||||
Serial.print(" ");Serial.print(tempArray[i],2);Serial.print(" |");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(" ");Serial.print(tempArray[i],2);Serial.print(" |");
|
||||
}
|
||||
}
|
||||
|
||||
//On affiche la trame associée:
|
||||
payloadFormatter.startSession(1);
|
||||
payloadDate = rtc.now();
|
||||
size = payloadFormatter.buildPayload(&payload, &payloadDate,tempArray);
|
||||
if(size != 0)
|
||||
{
|
||||
//Serial.print("LoRa packet --> ");Serial.print("size : ");Serial.print(size);Serial.println(" bytes");
|
||||
for(int i(0); i < size; i++)
|
||||
{
|
||||
payload[i] <= 0x0F ? Serial.print("0") : Serial.print(""); Serial.print(payload[i], HEX); Serial.print(" ");
|
||||
}
|
||||
Serial.printf("|%u-%u-%u %u:%u \n", payloadDate.day(),payloadDate.month(),payloadDate.year(),payloadDate.hour(),payloadDate.minute());
|
||||
}
|
||||
else
|
||||
Serial.print("Failed to build LoRa packet");
|
||||
|
||||
payloadFormatter.endSession();
|
||||
|
||||
#ifdef RADIO_ENABLED
|
||||
if(_timeCounter == 30 && size != 0)
|
||||
{
|
||||
_timeCounter = 0;
|
||||
Serial.printf("Sending data\n");
|
||||
radio.send(1, payload, size);
|
||||
}
|
||||
|
||||
_timeCounter++;
|
||||
#endif
|
||||
}
|
||||
|
||||
//On effectue la calibration
|
||||
if(digitalRead(PUSH_BUTTON) == 0)
|
||||
{
|
||||
delay(500);
|
||||
measureUnit.startOffsetComputing();
|
||||
}
|
||||
#ifdef RADIO_ENABLED
|
||||
radio.run();
|
||||
#endif
|
||||
measureUnit.run();
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#include "ThermistorSetting.h"
|
||||
|
||||
ThermistorSetting::ThermistorSetting(uint16_t beta, uint64_t rAt25) : _beta(beta), _rAt25(rAt25)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ThermistorSetting::~ThermistorSetting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint16_t ThermistorSetting::getBeta()
|
||||
{
|
||||
return _beta;
|
||||
}
|
||||
|
||||
uint64_t ThermistorSetting::getRat25()
|
||||
{
|
||||
return _rAt25;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#ifndef THERMISTORSETTING_H
|
||||
#define THERMISTORSETTING_H
|
||||
#include <Arduino.h> //Necessaire afin d'avoir les types : uintxx_t
|
||||
|
||||
class ThermistorSetting
|
||||
{
|
||||
public:
|
||||
ThermistorSetting(uint16_t beta, uint64_t rAt25);
|
||||
~ThermistorSetting();
|
||||
uint16_t getBeta();
|
||||
uint64_t getRat25();
|
||||
protected:
|
||||
private:
|
||||
uint16_t _beta;
|
||||
uint64_t _rAt25;
|
||||
};
|
||||
|
||||
#endif //THERMISTORSETTING_H
|
Loading…
Reference in New Issue
Block a user