diff --git a/lib/MeasureUnit/Adc.cpp b/lib/MeasureUnit/Adc.cpp index c39a2f6..dc8129c 100644 --- a/lib/MeasureUnit/Adc.cpp +++ b/lib/MeasureUnit/Adc.cpp @@ -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; +} diff --git a/lib/MeasureUnit/Adc.h b/lib/MeasureUnit/Adc.h index 43eb0ca..c22f267 100644 --- a/lib/MeasureUnit/Adc.h +++ b/lib/MeasureUnit/Adc.h @@ -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: }; diff --git a/lib/MeasureUnit/AdcSetting.h b/lib/MeasureUnit/AdcSetting.h index b1a9f6a..5d7a36c 100644 --- a/lib/MeasureUnit/AdcSetting.h +++ b/lib/MeasureUnit/AdcSetting.h @@ -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(); diff --git a/lib/MeasureUnit/Ads1115.cpp b/lib/MeasureUnit/Ads1115.cpp index 18fbec2..9062621 100644 --- a/lib/MeasureUnit/Ads1115.cpp +++ b/lib/MeasureUnit/Ads1115.cpp @@ -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; +} diff --git a/lib/MeasureUnit/Ads1115.h b/lib/MeasureUnit/Ads1115.h index 9132b4f..b215d37 100644 --- a/lib/MeasureUnit/Ads1115.h +++ b/lib/MeasureUnit/Ads1115.h @@ -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); diff --git a/lib/MeasureUnit/MeasureUnit.cpp b/lib/MeasureUnit/MeasureUnit.cpp index fe8e2cd..b7ccdc4 100644 --- a/lib/MeasureUnit/MeasureUnit.cpp +++ b/lib/MeasureUnit/MeasureUnit.cpp @@ -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; +} diff --git a/lib/MeasureUnit/MeasureUnit.h b/lib/MeasureUnit/MeasureUnit.h index a981c40..68fcc82 100644 --- a/lib/MeasureUnit/MeasureUnit.h +++ b/lib/MeasureUnit/MeasureUnit.h @@ -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 diff --git a/lib/MeasureUnit/MeasureUnit.ino b/lib/MeasureUnit/MeasureUnit.ino index eb1edb2..b63a9d1 100644 --- a/lib/MeasureUnit/MeasureUnit.ino +++ b/lib/MeasureUnit/MeasureUnit.ino @@ -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++; }