Ajout de la version asynchrone des méthodes pour la mesure de la température

This commit is contained in:
anschrammh 2020-01-12 13:37:09 +01:00
parent 185511d019
commit f231868ab9
8 changed files with 290 additions and 59 deletions

View File

@ -1,6 +1,6 @@
#include "Adc.h"
Adc::Adc() : _lastChannel(0), _adcSetting(0,0)
Adc::Adc() : _lastChannel(0), _adcSetting(0,0), _state(IDLING), _sampledValue(0), _numOfSamples(0), _elapsedTime(0)
{
//Serial.println("Adc constructor called");
}
@ -19,3 +19,25 @@ 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;
}

View File

@ -8,11 +8,22 @@ class Adc
virtual ~Adc() = 0;
virtual void begin() = 0;
virtual int32_t sampleValue(int16_t channel, boolean sgl = true) = 0;
virtual int32_t sampleValue() = 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:
@ -20,6 +31,11 @@ class Adc
int16_t _lastChannel;
AdcSetting _adcSetting;
//Async part
STATE _state;
double _sampledValue;
uint8_t _numOfSamples;
unsigned long _elapsedTime;
private:
};

View File

@ -8,7 +8,7 @@ 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();

View File

@ -25,9 +25,14 @@ void Ads1115::begin()
ads2.begin();
}
int32_t Ads1115::sampleValue(int16_t channel, boolean sgl)
double Ads1115::getQuantum()
{
int64_t total(0);
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());
@ -35,26 +40,15 @@ int32_t Ads1115::sampleValue(int16_t channel, boolean sgl)
}
//We divide
total /= getAdcSetting().getMeasureIteration();
total /= (double)getAdcSetting().getMeasureIteration();
//We return
return total;
}
int32_t Ads1115::sampleValue()
double Ads1115::sampleValue()
{
int64_t total(0);
for(int i(0); i < getAdcSetting().getMeasureIteration(); i++)
{
delay(getAdcSetting().getDelayBetweenIteration());
total += getReading();
}
//We divide
total /= getAdcSetting().getMeasureIteration();
//We return
return total;
return sampleValue(-1);
}
double Ads1115::sampleVoltage(int16_t channel, boolean sgl)
@ -72,7 +66,7 @@ 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);
@ -83,3 +77,50 @@ uint16_t Ads1115::getReading(int16_t channel, boolean sgl)
}
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;
_state = RESULT_READY;
}
break;
}
}
void Ads1115::startSample()
{
startSample(-1);
}
double Ads1115::getSampleVoltage()
{
return getSampleValue() * 0.125;
}

View File

@ -11,10 +11,17 @@ class Ads1115 : public Adc
~Ads1115();
virtual void begin();
virtual int32_t sampleValue(int16_t channel, boolean sgl = true);
virtual int32_t sampleValue();
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);

View File

@ -5,7 +5,17 @@ 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)
Adc &adc) : _analogInput(analogInput),
_thermistorCount(thermistorCount),
_precResistor(precResistor),
_thermistorSetting(thermistorSetting),
_adc(adc),
_globalOffset(0),
_error(OK),
_state(IDLING),
_channel(0),
_courant(0.0),
_triggerLevelOff(false)
{
//Allocation dynamique des différent tableaux
_temperatures = (double*) calloc(_thermistorCount, sizeof(double));
@ -138,10 +148,123 @@ void MeasureUnit::levelTemperaturesOff()
{
_rOffsetMap[i] = averageTemp - _temperatures[i];
}
}
double *MeasureUnit::getROffsetMap()
{
return _rOffsetMap;
}
void MeasureUnit::startTemperatureMeasurement()
{
switch(_state)
{
case IDLING:
_state = MEASURING;
_channel = 0;
break;
case MEASURING:
_adc.startSample(_channel);
if(_channel == 0) //Calcule du courant
{
if(_adc.isSampleReady())
{
double tension = _adc.getSampleVoltage();
_courant = tension / (double) _precResistor;
//Serial.println(tension);
_channel++;
}
}
else //Calcule des niveaux de tensions
{
if(_adc.isSampleReady())
{
_resistanceMap[_channel-1] = _adc.getSampleVoltage();
//Serial.println(_resistanceMap[_channel-1]);
_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.print("Debug voltage delta : ");Serial.println(_resistanceMap[i]);
#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 /= _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;
}
}
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;
}

View File

@ -17,6 +17,14 @@ class MeasureUnit
double *getTemperatures();
double *getROffsetMap();
//Async methods
enum STATE {IDLING, MEASURING, COMPUTING, MEASUREMENT_READY};
void startTemperatureMeasurement();
boolean isMeasurementReady();
double *getAsyncTemperatures();
void levelAsyncTemperaturesOff();
//End of assync methods
ERROR getError(){return _error;}
protected:
@ -34,6 +42,12 @@ class MeasureUnit
Adc &_adc;
ThermistorSetting _thermistorSetting;
//Async part
STATE _state;
uint8_t _channel;
double _courant;
boolean _triggerLevelOff; //Attribut permettant de savoir si un étalonnage a été demandé
};
#endif //MEASUREUNIT_H

View File

@ -16,7 +16,7 @@ double *tempArray = NULL;
//Objet de calcule de la temperature
ThermistorSetting thermistorSetting(3380, 10000);
//AdcSetting adcSetting(3300.0, 12, 310, 3);
AdcSetting adcSetting(3410.0, 15, 6, 10);
AdcSetting adcSetting(3410.0, 15, 6, 10);//6, 10);
Ads1115 adc;
MeasureUnit measureUnit(analogInput, 8, 990, thermistorSetting, adc);
//Objet de création des trames LoRa
@ -25,9 +25,10 @@ DateTime payloadDate(2020,12,26,8,42);
boolean data(false);
uint8_t *payload(NULL);
boolean calibrer(false);
unsigned long _time(millis());
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(1000);
Serial.println("Start setup");
@ -39,48 +40,57 @@ void setup() {
}
int compteur(0);
void loop() {
// put your main code here, to run repeatedly:
tempArray = measureUnit.getTemperatures();
//Version synchrone
//tempArray = measureUnit.getTemperatures();
//Version asynchrone :
measureUnit.startTemperatureMeasurement();
Serial.print("|");
for(int i(0); i < 8; i++)
//On peut tester si la conversion est terminée avec :
//if(measureUnit.isMeasurementReady())
tempArray = measureUnit.getAsyncTemperatures();
if(tempArray != NULL)
{
if(i != 7)
Serial.print("|");
for(int i(0); i < 8; i++)
{
Serial.print(" ");Serial.print(tempArray[i],2);Serial.print(" |");
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);
uint8_t 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.println();
}
else
{
Serial.print(" ");Serial.print(tempArray[i],2);Serial.println(" |");
}
Serial.print("Failed to build LoRa packet");
/*if(payloadFormatter.endSession())
Serial.println("Session ended successfully");*/
}
//On affiche la trame associée:
payloadFormatter.startSession(1);
uint8_t 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.println();
}
else
Serial.print("Failed to build LoRa packet");
if(payloadFormatter.endSession())
Serial.println("Session ended successfully");
//On effectue la calibration
if(compteur == 5)
if(millis() - _time > 5000 && !calibrer)
{
Serial.println("********************Starting calibration********************");
measureUnit.levelTemperaturesOff();
measureUnit.levelAsyncTemperaturesOff();
Serial.println("********************Ending calibration********************");
calibrer = true;
}
if(Serial.available())
@ -92,6 +102,4 @@ void loop() {
Serial.println("********************Ending calibration********************");
}
}
compteur++;
}