Compare commits
	
		
			8 Commits
		
	
	
		
			88a936198e
			...
			8c7c12178a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8c7c12178a | ||
|  | 240bfe370c | ||
|  | 7381d6d6e1 | ||
|  | a79db84f16 | ||
|  | ebba78c49b | ||
|  | 44e40b8ab3 | ||
|  | 3a3c01186c | ||
|  | 182901d5bc | 
							
								
								
									
										98
									
								
								lib/LTC2439Lib/LTC2439.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								lib/LTC2439Lib/LTC2439.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | #include "LTC2439.h" | ||||||
|  | #include <math.h> | ||||||
|  | 
 | ||||||
|  | #define DEBUG | ||||||
|  | 
 | ||||||
|  | LTC2439::LTC2439(uint8_t csPin, uint8_t sdoPin, double vref) :_csPin(csPin), _statusPin(sdoPin), _sampleTriggered(false), _vref(vref), _adcRes(16), _quantum(_vref / (pow(2, _adcRes)-1)), | ||||||
|  | _channelMap{0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15}, | ||||||
|  | _SPIsettings(500000, MSBFIRST,SPI_MODE0) | ||||||
|  | { | ||||||
|  |   pinMode(_csPin, OUTPUT); | ||||||
|  |   digitalWrite(_csPin, HIGH); | ||||||
|  |   SPI.begin(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LTC2439::setVref(double vref) | ||||||
|  | { | ||||||
|  |   _vref = vref; | ||||||
|  |   _quantum = _vref / (pow(2, _adcRes) - 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LTC2439::startAsyncSample(uint8_t channel, boolean sgl, boolean force) | ||||||
|  | { | ||||||
|  |   if(!_sampleTriggered || force) | ||||||
|  |   { | ||||||
|  |     //On envoie la demande de conversion
 | ||||||
|  |     //On sélectionne l'adc
 | ||||||
|  |     pinMode(_statusPin, INPUT); | ||||||
|  |     digitalWrite(_csPin, LOW); | ||||||
|  |     while(digitalRead(_statusPin)); | ||||||
|  |     uint8_t commande = 0b10100000; | ||||||
|  |     commande |= sgl << 4; | ||||||
|  | 	 | ||||||
|  | 	SPI.beginTransaction(_SPIsettings); | ||||||
|  |     SPI.transfer(commande | _channelMap[channel]); | ||||||
|  |     SPI.endTransaction(); | ||||||
|  | 	 | ||||||
|  |     digitalWrite(_csPin, HIGH); | ||||||
|  |     _sampleTriggered = true; | ||||||
|  | 	 | ||||||
|  | 	//restoreRadioSpi();
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | boolean LTC2439::asyncResultAvailable() | ||||||
|  | { | ||||||
|  |   //On désactive le bus SPI
 | ||||||
|  |   SPI.end(); | ||||||
|  |   //On regarde si la valeur est prête à être lue:
 | ||||||
|  |   pinMode(_statusPin, INPUT); | ||||||
|  |   digitalWrite(_csPin, LOW); | ||||||
|  |   boolean ready = !digitalRead(_statusPin); //Si la pin sdo est à l'état haut, c'est que la conversion n'est pas terminée.
 | ||||||
|  |   digitalWrite(_csPin, HIGH); | ||||||
|  |   //On réactive le bus SPI
 | ||||||
|  |   SPI.begin(); | ||||||
|  |   return ready; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | double LTC2439::convertToVoltage(int32_t value) | ||||||
|  | { | ||||||
|  |   value += 32767; | ||||||
|  |   value *= _quantum; | ||||||
|  |   return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t LTC2439::getAsyncValue() | ||||||
|  | { | ||||||
|  |   if(!_sampleTriggered) | ||||||
|  |     return -1; | ||||||
|  |      | ||||||
|  |   digitalWrite(_csPin, LOW); | ||||||
|  |    | ||||||
|  |   SPI.beginTransaction(_SPIsettings); | ||||||
|  |   int8_t bitsleft = 19; | ||||||
|  |   long result = 0;  | ||||||
|  |   while(bitsleft > 0)  | ||||||
|  |   { | ||||||
|  |     result <<= 8; | ||||||
|  |     result |= SPI.transfer(0); | ||||||
|  |     bitsleft -= 8; | ||||||
|  |   } | ||||||
|  |   SPI.endTransaction(); | ||||||
|  |    | ||||||
|  |   digitalWrite(_csPin, HIGH); | ||||||
|  |      | ||||||
|  |   result >>= -bitsleft; | ||||||
|  |   int pos = (result & 0b10000000000000000)>> 16; | ||||||
|  |   unsigned long mask = 0b1111111111111111; | ||||||
|  |   result &= mask; | ||||||
|  |      | ||||||
|  |   if(!pos && result != 0) | ||||||
|  |   { | ||||||
|  |     result = result | (~mask); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   _sampleTriggered = false; | ||||||
|  | 
 | ||||||
|  |   return result; | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								lib/LTC2439Lib/LTC2439.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/LTC2439Lib/LTC2439.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | /**
 | ||||||
|  | * Anatole SCHRAMM-HENRY | ||||||
|  | * Tim THUREL | ||||||
|  | * Projet température de la ruche GROUPE 3 | ||||||
|  | * Driver pour le LTC2439 fonctionne avec l'ESP8266 | ||||||
|  | * Méthodes asynchrones disponibles | ||||||
|  | * | ||||||
|  | * Tout droits réservés | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef LTC2439_H | ||||||
|  | #define LTC2439_H | ||||||
|  | 
 | ||||||
|  | #include <Arduino.h> | ||||||
|  | #include <SPI.h> | ||||||
|  | 
 | ||||||
|  | class LTC2439 | ||||||
|  | { | ||||||
|  |   public:            | ||||||
|  |     LTC2439(uint8_t csPin, uint8_t sdoPin, double vref = 3300); | ||||||
|  |     void setVref(double vref); | ||||||
|  |     double getVref(){return _vref;}; | ||||||
|  |     int32_t sampleValue(uint8_t channel, boolean sgl = true); | ||||||
|  |     int32_t sampleValue(); | ||||||
|  |     double sampleVoltage(uint8_t channel, boolean sgl = true); | ||||||
|  |     double sampleVoltage(); | ||||||
|  |     //Methodes asynchrones
 | ||||||
|  |     void startAsyncSample(uint8_t channel, boolean sgl = true, boolean force = false); | ||||||
|  |     boolean asyncResultAvailable(); | ||||||
|  |     double convertToVoltage(int32_t value); | ||||||
|  |     int32_t getAsyncValue(); | ||||||
|  |   protected: | ||||||
|  |   private: | ||||||
|  |     uint8_t _csPin, _statusPin; | ||||||
|  |     boolean _sampleTriggered; | ||||||
|  |     double _vref; //Delta de tension de la plage : vref-gnd en mV
 | ||||||
|  |     uint8_t _adcRes; | ||||||
|  |     double _quantum; | ||||||
|  |     const uint8_t _channelMap[16]; | ||||||
|  | 	const SPISettings _SPIsettings; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif //LTC2439_H
 | ||||||
							
								
								
									
										23
									
								
								lib/LTC2439Lib/examples/LTC2439Lib/LTC2439Lib.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/LTC2439Lib/examples/LTC2439Lib/LTC2439Lib.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | #include "LTC2439.h" | ||||||
|  | 
 | ||||||
|  | LTC2439 adc(2,12); | ||||||
|  | uint8_t channel(0); | ||||||
|  | 
 | ||||||
|  | void setup() | ||||||
|  | { | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   Serial.println("Starting setup"); | ||||||
|  |   Serial.println("End setup"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void loop() | ||||||
|  | { | ||||||
|  |   adc.startAsyncSample(channel); | ||||||
|  |    | ||||||
|  |   if(adc.asyncResultAvailable()) | ||||||
|  |   { | ||||||
|  |     int32_t raw = adc.getAsyncValue(); | ||||||
|  |     Serial.printf("Conversion done, result for channel %u : %d, tension : %.2f\n", channel, raw, adc.convertToVoltage(raw)); | ||||||
|  |     channel = channel == 15 ? 0 : channel + 1; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								lib/LTC2439Lib/keywords.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/LTC2439Lib/keywords.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | ####################################### | ||||||
|  | # Syntax Coloring Map LTC2439Lib | ||||||
|  | ####################################### | ||||||
|  | 
 | ||||||
|  | ####################################### | ||||||
|  | # Datatypes (KEYWORD1) | ||||||
|  | ####################################### | ||||||
|  | LTC2439	KEYWORD1 | ||||||
|  | 
 | ||||||
|  | ####################################### | ||||||
|  | # Methods and Functions (KEYWORD2) | ||||||
|  | ####################################### | ||||||
|  | setVref	KEYWORD2 | ||||||
|  | startAsyncSample	KEYWORD2 | ||||||
|  | asyncResultAvailable	KEYWORD2 | ||||||
|  | convertToVoltage	KEYWORD2 | ||||||
|  | getAsyncValue	KEYWORD2 | ||||||
|  | getVref	KEYWORD2 | ||||||
|  | ####################################### | ||||||
|  | # Constants (LITERAL1) | ||||||
|  | ####################################### | ||||||
|  | 
 | ||||||
| @ -1,7 +1,10 @@ | |||||||
| #include "LoRaRadio.h" | #include "LoRaRadio.h" | ||||||
| 
 | 
 | ||||||
|  | boolean _transmitted = false; | ||||||
|  | 
 | ||||||
| lmic_pinmap lmic_pins = {0}; | lmic_pinmap lmic_pins = {0}; | ||||||
| void (*LoRaRadio::downlinkHandler)(u1_t, u1_t, u1_t*) = NULL; | void (*LoRaRadio::downlinkHandler)(u1_t, u1_t, u1_t*) = NULL; | ||||||
|  | void (*LoRaRadio::sendCompleteHandler)(void) = NULL; | ||||||
| 
 | 
 | ||||||
| LoRaRadio::LoRaRadio(PinMap pinMap, dr_t dataRate, s1_t txPower) :_pinMap(pinMap), _dataRate(dataRate), _txPower(txPower) | LoRaRadio::LoRaRadio(PinMap pinMap, dr_t dataRate, s1_t txPower) :_pinMap(pinMap), _dataRate(dataRate), _txPower(txPower) | ||||||
| { | { | ||||||
| @ -46,7 +49,7 @@ void LoRaRadio::setRadioEUChannels() | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LoRaRadio::send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed) | void LoRaRadio::send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed) | ||||||
| { | {  | ||||||
|   if (LMIC.opmode & OP_TXRXPEND)  |   if (LMIC.opmode & OP_TXRXPEND)  | ||||||
|   { |   { | ||||||
|     //Serial.println(F("OP_TXRXPEND, not sending"));
 |     //Serial.println(F("OP_TXRXPEND, not sending"));
 | ||||||
| @ -69,6 +72,11 @@ void LoRaRadio::setDownlinkHandler(void (*funcP)(u1_t, u1_t, u1_t*)) | |||||||
|   downlinkHandler = funcP; |   downlinkHandler = funcP; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void LoRaRadio::setSendCompleteHandler(void (*funcP)(void)) | ||||||
|  | { | ||||||
|  |   sendCompleteHandler = funcP; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Here, we declare the onEvent function required by the LMIC |  * Here, we declare the onEvent function required by the LMIC | ||||||
|  */ |  */ | ||||||
| @ -78,6 +86,9 @@ void onEvent(ev_t ev) | |||||||
|   { |   { | ||||||
|     case EV_TXCOMPLETE: |     case EV_TXCOMPLETE: | ||||||
|       //Event telling us that the data was transmitted
 |       //Event telling us that the data was transmitted
 | ||||||
|  | 	  if(LoRaRadio::sendCompleteHandler != NULL) | ||||||
|  |           (*LoRaRadio::sendCompleteHandler)(); | ||||||
|  | 	   | ||||||
|       //It is also here that we check for downlinks
 |       //It is also here that we check for downlinks
 | ||||||
|       if(LMIC.dataLen) |       if(LMIC.dataLen) | ||||||
|       { |       { | ||||||
|  | |||||||
| @ -1,3 +1,13 @@ | |||||||
|  | /**
 | ||||||
|  | * Anatole SCHRAMM-HENRY | ||||||
|  | * Tim THUREL | ||||||
|  | * Projet température de la ruche GROUPE 3 | ||||||
|  | * Wrapper C++ afin d'utiliser la LMIC (en C) façon objets. | ||||||
|  | * Commenté en anglais pour le plaisir des yeux. | ||||||
|  | * | ||||||
|  | * Tout droits réservés | ||||||
|  | */ | ||||||
|  | 
 | ||||||
| #ifndef LORARADIO_H | #ifndef LORARADIO_H | ||||||
| #define LORARADIO_H | #define LORARADIO_H | ||||||
| 
 | 
 | ||||||
| @ -5,9 +15,10 @@ | |||||||
| #include <hal/hal.h> | #include <hal/hal.h> | ||||||
| #include <SPI.h> | #include <SPI.h> | ||||||
| #include <Arduino.h> | #include <Arduino.h> | ||||||
| /*
 | /**
 | ||||||
|  * Here, we define the onEvent function required by the LMIC | * Here, we define the onEvent function required by the LMIC | ||||||
|  */ | **/ | ||||||
|  | 
 | ||||||
| void onEvent(ev_t ev); | void onEvent(ev_t ev); | ||||||
| 
 | 
 | ||||||
| class PinMap | class PinMap | ||||||
| @ -37,12 +48,14 @@ class LoRaRadio | |||||||
|     void send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed = false); |     void send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed = false); | ||||||
|     void run(); |     void run(); | ||||||
|     void setDownlinkHandler(void (*funcP)(u1_t, u1_t, u1_t*)); |     void setDownlinkHandler(void (*funcP)(u1_t, u1_t, u1_t*)); | ||||||
|  | 	void setSendCompleteHandler(void (*funcP)(void)); | ||||||
|     void disableEUChannel(u1_t channel); |     void disableEUChannel(u1_t channel); | ||||||
|     void disableAllEUChannelsBut(u1_t channel); |     void disableAllEUChannelsBut(u1_t channel); | ||||||
| 
 | 
 | ||||||
|     //Function pointers used to interact with events
 |     //Function pointers used to interact with events
 | ||||||
|     //Parameters : dataLen, dataBeg, dataBuffer
 |     //Parameters : dataLen, dataBeg, dataBuffer
 | ||||||
|     static void (*downlinkHandler)(u1_t, u1_t, u1_t*); |     static void (*downlinkHandler)(u1_t, u1_t, u1_t*); | ||||||
|  | 	static void (*sendCompleteHandler)(void); | ||||||
|   protected: |   protected: | ||||||
|   private: |   private: | ||||||
|     dr_t _dataRate; |     dr_t _dataRate; | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ run	KEYWORD2 | |||||||
| setDownlinkHandler	KEYWORD2 | setDownlinkHandler	KEYWORD2 | ||||||
| disableEUChannel	KEYWORD2 | disableEUChannel	KEYWORD2 | ||||||
| disableAllEUChannelsBut	KEYWORD2 | disableAllEUChannelsBut	KEYWORD2 | ||||||
|  | setSendCompleteHandler	KEYWORD2 | ||||||
| 
 | 
 | ||||||
| ####################################### | ####################################### | ||||||
| # Constants (LITERAL1) | # Constants (LITERAL1) | ||||||
|  | |||||||
							
								
								
									
										201
									
								
								lib/MeasureUnit_ESP8266/MeasureUnit_ESP8266.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								lib/MeasureUnit_ESP8266/MeasureUnit_ESP8266.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,201 @@ | |||||||
|  | /**
 | ||||||
|  |  * 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 <ESP8266WiFi.h> | ||||||
|  | #include <RTClib.h> | ||||||
|  | #include "PayloadFormatter.h" | ||||||
|  | #include "LoRaRadio.h" | ||||||
|  | #include "ThermistorSetting.h" | ||||||
|  | #include "AdcSetting.h" | ||||||
|  | #include "STS21.h" | ||||||
|  | 
 | ||||||
|  | //#define RADIO_ENABLED
 | ||||||
|  | #define PUSH_BUTTON 0 | ||||||
|  | 
 | ||||||
|  | uint8_t analogInput[] = {0,1,2,3,4,5,6,7}; | ||||||
|  | double tempArray[8] = {21.58,21.65,21.54,21.48,21.68,21.75,21.54,21.59}; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * 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  | | ||||||
|  |  * |  -0.53  |  -0.49  |  -0.27  |  1.17  |  0.07  |  0.14  |  -0.02  |  -0.08  | | ||||||
|  |  * |  -0.62  |  -0.73  |  1.58  |  0.42  |  -0.27  |  0.09  |  -0.25  |  -0.21  | | ||||||
|  | 
 | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | //Objet de calcule de la temperature
 | ||||||
|  | ThermistorSetting thermistorSetting(3380, 10000); | ||||||
|  | //ThermistorSetting thermistorSetting(3650, 470);
 | ||||||
|  | //AdcSetting adcSetting(3300.0, 12, 310, 3);
 | ||||||
|  | AdcSetting adcSetting(3310, 15, 6, 10); | ||||||
|  | //MeasureUnit measureUnit(analogInput, 8, 99, thermistorSetting, adc);
 | ||||||
|  | //Objet de création des trames LoRa
 | ||||||
|  | PayloadFormatter payloadFormatter(2,4); | ||||||
|  | 
 | ||||||
|  | RTC_DS1307 rtc; | ||||||
|  | DateTime payloadDate; | ||||||
|  | STS21 sts21; | ||||||
|  | 
 | ||||||
|  | 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] = {15,3,LMIC_UNUSED_PIN}; | ||||||
|  | PinMap pinMap(2, LMIC_UNUSED_PIN, 0, dio); | ||||||
|  | LoRaRadio radio(pinMap); | ||||||
|  | 
 | ||||||
|  | void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data) | ||||||
|  | { | ||||||
|  |   Serial.println("Downlink received : "); | ||||||
|  |   for(uint8_t i(0); i < length; i++) | ||||||
|  |   { | ||||||
|  |     Serial.printf("%u -> %d\n",i,data[dataBeg + i]); | ||||||
|  |   } | ||||||
|  |   Serial.println(); | ||||||
|  | 
 | ||||||
|  |   //Action en fonction de l'octet de commande
 | ||||||
|  |   switch(data[dataBeg+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[dataBeg+1], data[dataBeg+2], data[dataBeg+3]+2000, data[dataBeg+4], data[dataBeg+5]); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         Serial.println("Action réglage RTC : paramètres insuffisants"); | ||||||
|  |       break; | ||||||
|  |     case 0x02: | ||||||
|  |       /*memcpy(screenTxt,(data+dataBeg+1), length-1);
 | ||||||
|  |       screenTxt[length-1] = '\0'; | ||||||
|  |       display.stopscroll(); | ||||||
|  |       display.clearDisplay(); | ||||||
|  |       display.setTextColor(WHITE); | ||||||
|  |       display.setCursor(0,15); | ||||||
|  |       display.setTextSize(2); | ||||||
|  |       display.print(screenTxt); | ||||||
|  |       display.display(); | ||||||
|  |       display.startscrollleft(0,16);*/ | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       Serial.println("Action inconnue"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void setup() { | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   delay(1000); | ||||||
|  |   Serial.println("Start setup"); | ||||||
|  |   WiFi.mode(WIFI_OFF); | ||||||
|  |   //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(50);
 | ||||||
|  |   radio.setDownlinkHandler(&(downlinkHandler)); | ||||||
|  |   #endif | ||||||
|  |   _time = millis(); | ||||||
|  |    | ||||||
|  |   if(rtc.begin()) | ||||||
|  |     Serial.println("RTC Ok!"); | ||||||
|  |   else | ||||||
|  |     Serial.println("RTC Fail!"); | ||||||
|  | 
 | ||||||
|  |   if(sts21.begin()) | ||||||
|  |   { | ||||||
|  |     Serial.println("Sensor present !"); | ||||||
|  |     sts21.setResolution(STS21::RES_14); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     Serial.println("Sensor missing !"); | ||||||
|  |    | ||||||
|  |   Serial.println("End setup"); | ||||||
|  |   Serial.println("|   T1    |   T2    |   T3    |   T4    |   T5    |   T6    |   T7    |   T8    |"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void loop() { | ||||||
|  |   //Version asynchrone :
 | ||||||
|  | 
 | ||||||
|  |   //On peut tester si la conversion est terminée avec :
 | ||||||
|  |    | ||||||
|  |   //measureUnit.getAsyncTemperatures() renvoie NULL si la recupération de la température n'est pas terminée
 | ||||||
|  |   //tempArray = //measureUnit.getAsyncTemperatures();
 | ||||||
|  |   double temp = sts21.getTemperature(); | ||||||
|  |   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, 22.5,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 ext temp : %.2f \n", payloadDate.day(),payloadDate.month(),payloadDate.year(),payloadDate.hour(),payloadDate.minute(), temp); | ||||||
|  |     } | ||||||
|  |     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++; | ||||||
|  |     delay(1000); | ||||||
|  |     #endif | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //On effectue la calibration
 | ||||||
|  |   #ifdef RADIO_ENABLED | ||||||
|  |   radio.run(); | ||||||
|  |   #endif | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								lib/MeasureUnit_ESP8266_LTC2439/AdcSetting.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/MeasureUnit_ESP8266_LTC2439/AdcSetting.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								lib/MeasureUnit_ESP8266_LTC2439/AdcSetting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/MeasureUnit_ESP8266_LTC2439/AdcSetting.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | #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
 | ||||||
							
								
								
									
										183
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,183 @@ | |||||||
|  | #include "MeasureUnit.h" | ||||||
|  | //#define DEBUG
 | ||||||
|  | 
 | ||||||
|  | MeasureUnit::MeasureUnit(uint16_t thermistorCount,  | ||||||
|  | uint64_t precResistor,  | ||||||
|  | ThermistorSettings thermistorSettings,  | ||||||
|  | LTC2439 &adc) : _thermistorCount(thermistorCount),  | ||||||
|  | _precResistor(precResistor), | ||||||
|  | _thermistorSettings(thermistorSettings),  | ||||||
|  | _adc(adc),  | ||||||
|  | _globalOffset(0),  | ||||||
|  | _error(OK),  | ||||||
|  | _state(IDLING), | ||||||
|  | _channel(0), | ||||||
|  | _offsetComputeIte(7), | ||||||
|  | _offsetCounter(7), | ||||||
|  | _courant{0.0, 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; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MeasureUnit::~MeasureUnit() | ||||||
|  | { | ||||||
|  |   if(_error != MALLOC_ERR) | ||||||
|  |   { | ||||||
|  |     free(_temperatures); | ||||||
|  |     free(_rOffsetMap); | ||||||
|  |     free(_resistanceMap); | ||||||
|  |     free(_rOffsetBuffer); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MeasureUnit::run() | ||||||
|  | { | ||||||
|  |   switch(_state) | ||||||
|  |   { | ||||||
|  |     case MEASURING: | ||||||
|  |       _adc.startAsyncSample(_channel); | ||||||
|  |        | ||||||
|  |       if(_adc.asyncResultAvailable()) | ||||||
|  |       { | ||||||
|  |         _resistanceMap[_channel] = _adc.convertToVoltage(_adc.getAsyncValue()); | ||||||
|  |        #ifdef DEBUG | ||||||
|  |        Serial.printf("Voltage %u  : %.2f\n", _channel, _resistanceMap[_channel]); | ||||||
|  |        #endif | ||||||
|  |        _channel++; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       //Fin de la partie d'acquisition
 | ||||||
|  |       if(_channel == _thermistorCount) | ||||||
|  |       { | ||||||
|  |         _state = COMPUTING; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case COMPUTING : | ||||||
|  |       //Ici nous calculons les temperatures des thermistances (8 à la fois)
 | ||||||
|  |       _courant[0] = _resistanceMap[0] / (double) _precResistor; | ||||||
|  |       for(int i(0); i < 8; i++) | ||||||
|  |       { | ||||||
|  |         //Calcule de delta :
 | ||||||
|  |         if(i < 7) | ||||||
|  |           _resistanceMap[i] = _resistanceMap[i+1] - _resistanceMap[i]; | ||||||
|  |         else | ||||||
|  |           _resistanceMap[i] = _adc.getVref() - _resistanceMap[i]; | ||||||
|  |         #ifdef DEBUG | ||||||
|  |         Serial.printf("Debug voltage delta : %u -> %.2f\n",i,_resistanceMap[i]); | ||||||
|  |         #endif | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       _courant[1] = _resistanceMap[8] / (double) _precResistor; | ||||||
|  |       for(int i(8); i < 16; i++) | ||||||
|  |       { | ||||||
|  |         //Calcule de delta :
 | ||||||
|  |         if(i < 15) | ||||||
|  |           _resistanceMap[i] = _resistanceMap[i+1] - _resistanceMap[i]; | ||||||
|  |         else | ||||||
|  |           _resistanceMap[i] = _adc.getVref() - _resistanceMap[i]; | ||||||
|  |         #ifdef DEBUG | ||||||
|  |         Serial.printf("Debug voltage delta : %u -> %.2f\n",i,_resistanceMap[i]); | ||||||
|  |         #endif | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       //Calcule de la température (8 à la fois) :
 | ||||||
|  |       for(int i(0); i < 8; i++) | ||||||
|  |       { | ||||||
|  |         _resistanceMap[i] /= _courant[0]; | ||||||
|  |         _temperatures[i] = computeTemperature(_thermistorSettings.getBeta(), _resistanceMap[i], _thermistorSettings.getRat25()); | ||||||
|  |         _temperatures[i] += _rOffsetMap[i] + _globalOffset; | ||||||
|  | 
 | ||||||
|  |         #ifdef DEBUG | ||||||
|  |         Serial.printf("Temperature %u -> %.2f\n", i, _temperatures[i]); | ||||||
|  |         #endif | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       for(int i(8); i < 16; i++) | ||||||
|  |       { | ||||||
|  |         _resistanceMap[i] /= _courant[1]; | ||||||
|  |         _temperatures[i] = computeTemperature(_thermistorSettings.getBeta(), _resistanceMap[i], _thermistorSettings.getRat25()); | ||||||
|  |         _temperatures[i] += _rOffsetMap[i] + _globalOffset; | ||||||
|  | 
 | ||||||
|  |         #ifdef DEBUG | ||||||
|  |         Serial.printf("Temperature %u -> %.2f\n", i, _temperatures[i]); | ||||||
|  |         #endif | ||||||
|  |       } | ||||||
|  |        _state = MEASUREMENT_READY; | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | double *MeasureUnit::getROffsetMap() | ||||||
|  | { | ||||||
|  |   return _rOffsetMap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | boolean MeasureUnit::startTemperatureMeasurement() | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |   if(_state == IDLING) | ||||||
|  |   { | ||||||
|  |     _state = MEASURING; | ||||||
|  |     _channel = 0; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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() | ||||||
|  | { | ||||||
|  |    | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | #ifndef MEASUREUNIT_H | ||||||
|  | #define MEASUREUNIT_H | ||||||
|  | #include <LTC2439.h> | ||||||
|  | #include "ThermistorSettings.h" | ||||||
|  | 
 | ||||||
|  | class MeasureUnit | ||||||
|  | { | ||||||
|  |   public: | ||||||
|  |     enum ERROR {OK = 0, MALLOC_ERR = 1}; | ||||||
|  |     MeasureUnit(uint16_t thermistorCount, uint64_t precResistor, ThermistorSettings thermistorSettings, LTC2439 &adc); | ||||||
|  |     ~MeasureUnit(); | ||||||
|  |     void init(); | ||||||
|  |     void run(); | ||||||
|  |      | ||||||
|  |     void setGlobalTempOffset(double offset); | ||||||
|  |     double getGlobalTempOffset(); | ||||||
|  |     double *getROffsetMap(); | ||||||
|  | 
 | ||||||
|  |     //Async methods
 | ||||||
|  |     enum STATE {IDLING, MEASURING, COMPUTING, MEASUREMENT_READY}; | ||||||
|  |     boolean startTemperatureMeasurement(); | ||||||
|  |     boolean isMeasurementReady(); | ||||||
|  |     double *getAsyncTemperatures(); | ||||||
|  |     //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)
 | ||||||
|  |     uint16_t _thermistorCount; | ||||||
|  |     uint64_t _precResistor; | ||||||
|  |     ERROR _error; | ||||||
|  | 
 | ||||||
|  |     LTC2439 &_adc; | ||||||
|  |     ThermistorSettings _thermistorSettings; | ||||||
|  |      | ||||||
|  |     //Async part
 | ||||||
|  |     STATE _state; | ||||||
|  |     uint8_t _channel, _offsetComputeIte,_offsetCounter; | ||||||
|  |     double _courant[2]; | ||||||
|  |     boolean _triggerLevelOff; //Attribut permettant de savoir si un étalonnage a été demandé
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif //MEASUREUNIT_H
 | ||||||
							
								
								
									
										198
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit_ESP8266_LTC2439.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								lib/MeasureUnit_ESP8266_LTC2439/MeasureUnit_ESP8266_LTC2439.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,198 @@ | |||||||
|  | /**
 | ||||||
|  |  * 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 | ||||||
|  |  * Tim THUREL | ||||||
|  |  * Version compatible avce le LTC2439 | ||||||
|  |  * 10/05/2020 | ||||||
|  |  */ | ||||||
|  | #include <ESP8266WiFi.h> | ||||||
|  | #include <RTClib.h> | ||||||
|  | #include <PayloadFormatter.h> | ||||||
|  | #include <LoRaRadio.h> | ||||||
|  | #include <LTC2439.h> | ||||||
|  | #include "MeasureUnit.h" | ||||||
|  | #include "ThermistorSettings.h" | ||||||
|  | #include <STS21.h> | ||||||
|  | 
 | ||||||
|  | //#define RADIO_ENABLED
 | ||||||
|  | #define PUSH_BUTTON 0 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * 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  | | ||||||
|  |  * |  -0.53  |  -0.49  |  -0.27  |  1.17  |  0.07  |  0.14  |  -0.02  |  -0.08  | | ||||||
|  |  * |  -0.62  |  -0.73  |  1.58  |  0.42  |  -0.27  |  0.09  |  -0.25  |  -0.21  | | ||||||
|  | 
 | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | //Objet de calcule de la température
 | ||||||
|  | LTC2439 adc(2,12); | ||||||
|  | 
 | ||||||
|  | ThermistorSettings thermistorSettings(3380, 10000); | ||||||
|  | MeasureUnit measureUnit(16, 1000, thermistorSettings, adc); | ||||||
|  | //Objet de création des trames LoRa
 | ||||||
|  | PayloadFormatter payloadFormatter(1,16); | ||||||
|  | 
 | ||||||
|  | RTC_DS1307 rtc; | ||||||
|  | DateTime payloadDate; | ||||||
|  | STS21 sts21; | ||||||
|  | 
 | ||||||
|  | boolean data(false); | ||||||
|  | uint8_t *payload(NULL), _timeCounter(0), size(0), _channel(0); | ||||||
|  | boolean calibrer(false); | ||||||
|  | unsigned long _time(0); | ||||||
|  | double *tempArray = NULL; | ||||||
|  | /*
 | ||||||
|  |  * 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] = {15,3,LMIC_UNUSED_PIN}; | ||||||
|  | PinMap pinMap(2, LMIC_UNUSED_PIN, 0, dio); | ||||||
|  | LoRaRadio radio(pinMap); | ||||||
|  | 
 | ||||||
|  | void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data) | ||||||
|  | { | ||||||
|  |   Serial.println("Downlink received : "); | ||||||
|  |   for(uint8_t i(0); i < length; i++) | ||||||
|  |   { | ||||||
|  |     Serial.printf("%u -> %d\n",i,data[dataBeg + i]); | ||||||
|  |   } | ||||||
|  |   Serial.println(); | ||||||
|  | 
 | ||||||
|  |   //Action en fonction de l'octet de commande
 | ||||||
|  |   switch(data[dataBeg+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[dataBeg+1], data[dataBeg+2], data[dataBeg+3]+2000, data[dataBeg+4], data[dataBeg+5]); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         Serial.println("Action réglage RTC : paramètres insuffisants"); | ||||||
|  |       break; | ||||||
|  |     case 0x02: | ||||||
|  |       /*memcpy(screenTxt,(data+dataBeg+1), length-1);
 | ||||||
|  |       screenTxt[length-1] = '\0'; | ||||||
|  |       display.stopscroll(); | ||||||
|  |       display.clearDisplay(); | ||||||
|  |       display.setTextColor(WHITE); | ||||||
|  |       display.setCursor(0,15); | ||||||
|  |       display.setTextSize(2); | ||||||
|  |       display.print(screenTxt); | ||||||
|  |       display.display(); | ||||||
|  |       display.startscrollleft(0,16);*/ | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       Serial.println("Action inconnue"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void setup() { | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   delay(1000); | ||||||
|  |   Serial.println("Start setup"); | ||||||
|  |   WiFi.mode(WIFI_OFF); | ||||||
|  |   //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(50);
 | ||||||
|  |   radio.setDownlinkHandler(&(downlinkHandler)); | ||||||
|  |   #endif | ||||||
|  |   _time = millis(); | ||||||
|  |    | ||||||
|  |   if(rtc.begin()) | ||||||
|  |     Serial.println("RTC Ok!"); | ||||||
|  |   else | ||||||
|  |     Serial.println("RTC Fail!"); | ||||||
|  | 
 | ||||||
|  |   if(sts21.begin()) | ||||||
|  |   { | ||||||
|  |     Serial.println("Sensor present !"); | ||||||
|  |     sts21.setResolution(STS21::RES_14); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     Serial.println("Sensor missing !"); | ||||||
|  |    | ||||||
|  |   Serial.println("End setup"); | ||||||
|  |   Serial.println("|   T1    |   T2    |   T3    |   T4    |   T5    |   T6    |   T7    |   T8    |   T9    |   T10   |   T11   |   T12   |   T13   |   T14   |   T15   |   T16   |"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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(); | ||||||
|  |    | ||||||
|  |   double temp = sts21.getTemperature(); | ||||||
|  |    | ||||||
|  |   if(tempArray != NULL) | ||||||
|  |   { | ||||||
|  |     Serial.print("|"); | ||||||
|  |     for(int i(0); i < 16; i++) | ||||||
|  |     { | ||||||
|  |       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, 22.5,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 ext temp : %.2f \n", payloadDate.day(),payloadDate.month(),payloadDate.year(),payloadDate.hour(),payloadDate.minute(), temp); | ||||||
|  |     } | ||||||
|  |     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++; | ||||||
|  |     delay(1000); | ||||||
|  |     #endif | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //On effectue la calibration
 | ||||||
|  |   #ifdef RADIO_ENABLED | ||||||
|  |   radio.run(); | ||||||
|  |   #endif | ||||||
|  |   measureUnit.run(); | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								lib/MeasureUnit_ESP8266_LTC2439/ThermistorSettings.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/MeasureUnit_ESP8266_LTC2439/ThermistorSettings.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #include "ThermistorSettings.h" | ||||||
|  | 
 | ||||||
|  | ThermistorSettings::ThermistorSettings(uint16_t beta, uint64_t rAt25) : _beta(beta), _rAt25(rAt25) | ||||||
|  | { | ||||||
|  |    | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ThermistorSettings::~ThermistorSettings() | ||||||
|  | { | ||||||
|  |    | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint16_t ThermistorSettings::getBeta() | ||||||
|  | { | ||||||
|  |   return _beta; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint64_t ThermistorSettings::getRat25() | ||||||
|  | { | ||||||
|  |   return _rAt25; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								lib/MeasureUnit_ESP8266_LTC2439/ThermistorSettings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/MeasureUnit_ESP8266_LTC2439/ThermistorSettings.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #ifndef THERMISTORSETTINGS_H | ||||||
|  | #define THERMISTORSETTINGS_H | ||||||
|  | #include <Arduino.h> //Necessaire afin d'avoir les types : uintxx_t | ||||||
|  | 
 | ||||||
|  | class ThermistorSettings | ||||||
|  | { | ||||||
|  |   public: | ||||||
|  |     ThermistorSettings(uint16_t beta, uint64_t rAt25); | ||||||
|  |     ~ThermistorSettings(); | ||||||
|  |     uint16_t getBeta(); | ||||||
|  |     uint64_t getRat25(); | ||||||
|  |   protected: | ||||||
|  |   private: | ||||||
|  |     uint16_t _beta; | ||||||
|  |     uint64_t _rAt25; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif //THERMISTORSETTINGS_H
 | ||||||
							
								
								
									
										34
									
								
								lib/MeasureUnit_ESP8266_LTC2439/keywords.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/MeasureUnit_ESP8266_LTC2439/keywords.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | ####################################### | ||||||
|  | # Syntax Coloring Map MeasureUnit | ||||||
|  | ####################################### | ||||||
|  | 
 | ||||||
|  | ####################################### | ||||||
|  | # Datatypes (KEYWORD1) | ||||||
|  | ####################################### | ||||||
|  | ThermistorSettings	KEYWORD1 | ||||||
|  | AdcSetting	KEYWORD1 | ||||||
|  | MeasureUnit	KEYWORD1 | ||||||
|  | OK	KEYWORD1 | ||||||
|  | MALLOC_ERR	KEYWORD1 | ||||||
|  | 
 | ||||||
|  | ####################################### | ||||||
|  | # Methods and Functions (KEYWORD2) | ||||||
|  | ####################################### | ||||||
|  | getBeta	KEYWORD2 | ||||||
|  | getRat25	KEYWORD2 | ||||||
|  | getMeasureIteration	KEYWORD2 | ||||||
|  | getDelayBetweenIteration	KEYWORD2 | ||||||
|  | getQuantum	KEYWORD2 | ||||||
|  | getVref	KEYWORD2 | ||||||
|  | setGlobalTempOffset	KEYWORD2 | ||||||
|  | getGlobalTempOffset	KEYWORD2 | ||||||
|  | getROffsetMap	KEYWORD2 | ||||||
|  | startTemperatureMeasurement	KEYWORD2 | ||||||
|  | isMeasurementReady	KEYWORD2 | ||||||
|  | getAsyncTemperatures	KEYWORD2 | ||||||
|  | getError	KEYWORD2 | ||||||
|  | 
 | ||||||
|  | ####################################### | ||||||
|  | # Constants (LITERAL1) | ||||||
|  | ####################################### | ||||||
|  | ERROR	LITERAL1 | ||||||
							
								
								
									
										43
									
								
								lib/MeasureUnit_TTGO/Adc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/MeasureUnit_TTGO/Adc.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								lib/MeasureUnit_TTGO/Adc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								lib/MeasureUnit_TTGO/Adc.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | #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
 | ||||||
							
								
								
									
										19
									
								
								lib/MeasureUnit_TTGO/AdcSetting.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/MeasureUnit_TTGO/AdcSetting.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								lib/MeasureUnit_TTGO/AdcSetting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/MeasureUnit_TTGO/AdcSetting.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | #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
 | ||||||
							
								
								
									
										127
									
								
								lib/MeasureUnit_TTGO/Ads1115.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								lib/MeasureUnit_TTGO/Ads1115.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								lib/MeasureUnit_TTGO/Ads1115.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/MeasureUnit_TTGO/Ads1115.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #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
 | ||||||
							
								
								
									
										134
									
								
								lib/MeasureUnit_TTGO/Ads1115V2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								lib/MeasureUnit_TTGO/Ads1115V2.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,134 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								lib/MeasureUnit_TTGO/Ads1115V2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/MeasureUnit_TTGO/Ads1115V2.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #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
 | ||||||
							
								
								
									
										375
									
								
								lib/MeasureUnit_TTGO/MeasureUnit.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								lib/MeasureUnit_TTGO/MeasureUnit.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,375 @@ | |||||||
|  | #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)); | ||||||
|  | } | ||||||
							
								
								
									
										57
									
								
								lib/MeasureUnit_TTGO/MeasureUnit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								lib/MeasureUnit_TTGO/MeasureUnit.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | #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
 | ||||||
| @ -20,47 +20,24 @@ | |||||||
| 
 | 
 | ||||||
| uint8_t analogInput[] = {0,1,2,3,4,5,6,7}; | uint8_t analogInput[] = {0,1,2,3,4,5,6,7}; | ||||||
| double *tempArray = NULL; | double *tempArray = NULL; | ||||||
|  | char screenTxt[30] = "LES ALEAS DU DIRECT"; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Liste des offsets trouvés |  * Liste des offsets trouvés | ||||||
|  * |  -0.49  |  0.36  |  -0.29  |  0.38  |  0.44  |  -0.35  |  -0.21  |  0.14  | |  * |  -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.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  | |  * |  -0.99  |  -0.06  |  -0.74  |  2.24  |  0.73  |  -0.86  |  -0.68  |  0.35  | | ||||||
|  |  * |  -0.53  |  -0.49  |  -0.27  |  1.17  |  0.07  |  0.14  |  -0.02  |  -0.08  | | ||||||
|  |  * |  -0.62  |  -0.73  |  1.58  |  0.42  |  -0.27  |  0.09  |  -0.25  |  -0.21  | | ||||||
| 
 | 
 | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| 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
 | //Objet de calcule de la temperature
 | ||||||
| //ThermistorSetting thermistorSetting(3380, 10000);
 | ThermistorSetting thermistorSetting(3380, 10000); | ||||||
| ThermistorSetting thermistorSetting(3650, 470); | //ThermistorSetting thermistorSetting(3650, 470);
 | ||||||
| //AdcSetting adcSetting(3300.0, 12, 310, 3);
 | //AdcSetting adcSetting(3300.0, 12, 310, 3);
 | ||||||
| AdcSetting adcSetting(3320, 15, 6, 10); | AdcSetting adcSetting(3310, 15, 6, 10); | ||||||
| Ads1115 adc; | Ads1115 adc; | ||||||
| MeasureUnit measureUnit(analogInput, 8, 990, thermistorSetting, adc); | MeasureUnit measureUnit(analogInput, 8, 990, thermistorSetting, adc); | ||||||
| //MeasureUnit measureUnit(analogInput, 8, 99, thermistorSetting, adc);
 | //MeasureUnit measureUnit(analogInput, 8, 99, thermistorSetting, adc);
 | ||||||
| @ -91,6 +68,45 @@ u1_t dio[3] = {26,33,32}; | |||||||
| PinMap pinMap(18, LMIC_UNUSED_PIN, 14, dio); | PinMap pinMap(18, LMIC_UNUSED_PIN, 14, dio); | ||||||
| LoRaRadio radio(pinMap); | LoRaRadio radio(pinMap); | ||||||
| 
 | 
 | ||||||
|  | void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data) | ||||||
|  | { | ||||||
|  |   Serial.println("Downlink received : "); | ||||||
|  |   for(uint8_t i(0); i < length; i++) | ||||||
|  |   { | ||||||
|  |     Serial.printf("%u -> %d\n",i,data[dataBeg + i]); | ||||||
|  |   } | ||||||
|  |   Serial.println(); | ||||||
|  | 
 | ||||||
|  |   //Action en fonction de l'octet de commande
 | ||||||
|  |   switch(data[dataBeg+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[dataBeg+1], data[dataBeg+2], data[dataBeg+3]+2000, data[dataBeg+4], data[dataBeg+5]); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         Serial.println("Action réglage RTC : paramètres insuffisants"); | ||||||
|  |       break; | ||||||
|  |     case 0x02: | ||||||
|  |       memcpy(screenTxt,(data+dataBeg+1), length-1); | ||||||
|  |       screenTxt[length-1] = '\0'; | ||||||
|  |       display.stopscroll(); | ||||||
|  |       display.clearDisplay(); | ||||||
|  |       display.setTextColor(WHITE); | ||||||
|  |       display.setCursor(0,15); | ||||||
|  |       display.setTextSize(2); | ||||||
|  |       display.print(screenTxt); | ||||||
|  |       display.display(); | ||||||
|  |       display.startscrollleft(0,16); | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       Serial.println("Action inconnue"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void setup() { | void setup() { | ||||||
|   Serial.begin(115200); |   Serial.begin(115200); | ||||||
|   delay(1000); |   delay(1000); | ||||||
| @ -107,7 +123,7 @@ void setup() { | |||||||
|    * réception (Downlink). En effet ce slot doit durer 2 secondes et il peut durer moins en raison |    * réception (Downlink). En effet ce slot doit durer 2 secondes et il peut durer moins en raison | ||||||
|    * d'imprécisions d'horloge. |    * d'imprécisions d'horloge. | ||||||
|    */ |    */ | ||||||
|   radio.setMCUClockError(); |   radio.setMCUClockError(50); | ||||||
|   radio.setDownlinkHandler(&(downlinkHandler)); |   radio.setDownlinkHandler(&(downlinkHandler)); | ||||||
|   #endif |   #endif | ||||||
|   //Adc init
 |   //Adc init
 | ||||||
| @ -125,7 +141,7 @@ void setup() { | |||||||
|     display.setTextColor(WHITE); |     display.setTextColor(WHITE); | ||||||
|     display.setCursor(0,15); |     display.setCursor(0,15); | ||||||
|     display.setTextSize(2); |     display.setTextSize(2); | ||||||
|     display.print("LES ALEAS DU DIRECT"); |     display.print(screenTxt); | ||||||
|     display.display(); |     display.display(); | ||||||
|   } |   } | ||||||
|   else Serial.println("SCREEN Fail!"); |   else Serial.println("SCREEN Fail!"); | ||||||
							
								
								
									
										21
									
								
								lib/MeasureUnit_TTGO/ThermistorSetting.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/MeasureUnit_TTGO/ThermistorSetting.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								lib/MeasureUnit_TTGO/ThermistorSetting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/MeasureUnit_TTGO/ThermistorSetting.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #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
 | ||||||
| @ -1,3 +1,12 @@ | |||||||
|  | /**
 | ||||||
|  | * Anatole SCHRAMM-HENRY | ||||||
|  | * Tim THUREL | ||||||
|  | * Projet température de la ruche GROUPE 3 | ||||||
|  | * Objet PayloadFormatter permettant de générer les trames contenants les températures, la date et les numéros de trames | ||||||
|  | * | ||||||
|  | * Tout droits réservés | ||||||
|  | */ | ||||||
|  | 
 | ||||||
| #ifndef PAYLOADFORMATTER_H | #ifndef PAYLOADFORMATTER_H | ||||||
| #define PAYLOADFORMATTER_H | #define PAYLOADFORMATTER_H | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | |||||||
							
								
								
									
										199
									
								
								src/app/app.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/app/app.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | /**
 | ||||||
|  | * Code source de l'application (qui a servi de démo pour la présentation finale) | ||||||
|  | * Anatole SCHRAMM-HENRY et Tim THUREL | ||||||
|  | *  | ||||||
|  | * Récupère 16 mesures de température (une barrette) et les envoies en LoRa à interval de temps régulier | ||||||
|  | **/ | ||||||
|  | 
 | ||||||
|  | #include <ESP8266WiFi.h> | ||||||
|  | #include <RTClib.h> | ||||||
|  | #include <PayloadFormatter.h> | ||||||
|  | #include <LoRaRadio.h> | ||||||
|  | #include <LTC2439.h> | ||||||
|  | #include <MeasureUnit.h> | ||||||
|  | #include <ThermistorSettings.h> | ||||||
|  | #include <AdcSetting.h> | ||||||
|  | #include <STS21.h> | ||||||
|  | 
 | ||||||
|  | #define RADIO_ENABLED | ||||||
|  | #define ONE_CHANNEL_GW | ||||||
|  | //INTERVAL_ENVOI en secondes (15 minutes)
 | ||||||
|  | #define INTERVAL_ENVOI 15*60  | ||||||
|  | 
 | ||||||
|  | //16 CS, 12 MISO
 | ||||||
|  | LTC2439 adc(16,12); | ||||||
|  | 
 | ||||||
|  | //Beta de 3380, Résistance à 25 °C de 10K Ohm
 | ||||||
|  | ThermistorSettings thermistorSettings(3380, 10000); | ||||||
|  | 
 | ||||||
|  | //16 thermistances sur 1 rangée, résistance de précision de 1k Ohm
 | ||||||
|  | MeasureUnit measureUnit(16, 1000, thermistorSettings, adc); | ||||||
|  | 
 | ||||||
|  | //Objet de création des trames LoRa
 | ||||||
|  | PayloadFormatter payloadFormatter(2,8); | ||||||
|  | 
 | ||||||
|  | RTC_DS1307 rtc; | ||||||
|  | DateTime payloadDate; | ||||||
|  | STS21 sts21; | ||||||
|  | 
 | ||||||
|  | boolean data(false); | ||||||
|  | uint8_t *payload(NULL), size(0), _channel(0); | ||||||
|  | double *tempArray = NULL; | ||||||
|  | 
 | ||||||
|  | boolean sendTriggered(false); | ||||||
|  | uint16_t counterSave(1); | ||||||
|  | unsigned long ts(millis()); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  | * Partie d'initialisation de la radio | ||||||
|  | * et définition des identifiants TTN | ||||||
|  | **/ | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | u1_t dio[3] = {15,3,LMIC_UNUSED_PIN}; | ||||||
|  | PinMap pinMap(2, LMIC_UNUSED_PIN, 0, dio); | ||||||
|  | LoRaRadio radio(pinMap, DR_SF9); | ||||||
|  | 
 | ||||||
|  | void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data) | ||||||
|  | { | ||||||
|  |   Serial.println("Downlink received : "); | ||||||
|  |   for(uint8_t i(0); i < length; i++) | ||||||
|  |   { | ||||||
|  |     Serial.printf("%u -> %d\n",i,data[dataBeg + i]); | ||||||
|  |   } | ||||||
|  |   Serial.println(); | ||||||
|  | 
 | ||||||
|  |   //Action en fonction de l'octet de commande
 | ||||||
|  |   switch(data[dataBeg+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[dataBeg+1], data[dataBeg+2], data[dataBeg+3]+2000, data[dataBeg+4], data[dataBeg+5]); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         Serial.println("Action réglage RTC : paramètres insuffisants"); | ||||||
|  |       break; | ||||||
|  |     case 0x02: | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       Serial.println("Action inconnue"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void sendCompleteHandler() | ||||||
|  | { | ||||||
|  |   Serial.printf("Send is done !\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void setup()  | ||||||
|  | { | ||||||
|  |   Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); | ||||||
|  |   //Met le pin 3 RX en GPIO
 | ||||||
|  |   pinMode(3, FUNCTION_3); | ||||||
|  |   delay(1000); | ||||||
|  |   Serial.println("Start setup"); | ||||||
|  |   WiFi.mode(WIFI_OFF); | ||||||
|  | 
 | ||||||
|  |   //Initialisation de la radio
 | ||||||
|  |   #ifdef RADIO_ENABLED | ||||||
|  |   radio.init(); | ||||||
|  |   radio.setTTNSession(0x1, DEVADDR, NWKSKEY, APPSKEY); | ||||||
|  |   radio.setRadioEUChannels(); | ||||||
|  |   #ifdef ONE_CHANNEL_GW | ||||||
|  |   radio.disableAllEUChannelsBut(0); | ||||||
|  |   #endif | ||||||
|  |   /**
 | ||||||
|  |   * 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(); | ||||||
|  |   #endif | ||||||
|  |   //Enregistrement des callbacks d'evenements
 | ||||||
|  |   radio.setDownlinkHandler(&(downlinkHandler)); | ||||||
|  |   radio.setSendCompleteHandler(&(sendCompleteHandler)); | ||||||
|  | 
 | ||||||
|  |   if(rtc.begin()) | ||||||
|  |     Serial.println("RTC Ok!"); | ||||||
|  |   else | ||||||
|  |     Serial.println("RTC Fail!"); | ||||||
|  | 
 | ||||||
|  |   if(sts21.begin()) | ||||||
|  |   { | ||||||
|  |     Serial.println("Sensor present !"); | ||||||
|  |     sts21.setResolution(STS21::RES_14); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     Serial.println("Sensor missing !"); | ||||||
|  |    | ||||||
|  |   Serial.println("End setup"); | ||||||
|  |   Serial.println("|   T1    |   T2    |   T3    |   T4    |   T5    |   T6    |   T7    |   T8    |   T9    |   T10   |   T11   |   T12   |   T13   |   T14   |   T15   |   T16   |"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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(); | ||||||
|  |    | ||||||
|  |   double externalTemp = sts21.getTemperature(); | ||||||
|  |    | ||||||
|  |   if(tempArray != NULL) | ||||||
|  |   { | ||||||
|  |     Serial.print("|"); | ||||||
|  |     for(int i(0); i < 16; i++) | ||||||
|  |     { | ||||||
|  |       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, externalTemp,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 ext temp : %.2f \n", payloadDate.day(),payloadDate.month(),payloadDate.year(),payloadDate.hour(),payloadDate.minute(), externalTemp); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       Serial.print("Failed to build LoRa packet"); | ||||||
|  |      | ||||||
|  |     payloadFormatter.endSession(); | ||||||
|  |      | ||||||
|  |     #ifdef RADIO_ENABLED | ||||||
|  | 
 | ||||||
|  |     //Envoie des trames à interval de temps régulier
 | ||||||
|  |     if(millis() - ts > INTERVAL_ENVOI*1000 && size != 0) | ||||||
|  |     { | ||||||
|  |       Serial.println("Sending data"); | ||||||
|  |       radio.send(1, payload, size); | ||||||
|  | 
 | ||||||
|  |       ts = millis(); | ||||||
|  |     } | ||||||
|  |     #endif | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #ifdef RADIO_ENABLED | ||||||
|  |   radio.run(); | ||||||
|  |   #endif | ||||||
|  |   measureUnit.run(); | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								test/TestLibAdc/TestLibAdc.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								test/TestLibAdc/TestLibAdc.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | #include "Ads1115V2.h" | ||||||
|  | 
 | ||||||
|  | AdcSetting adcSetting(3300.0, 15, 1, 10); | ||||||
|  | Ads1115V2 adc; | ||||||
|  | 
 | ||||||
|  | uint8_t channel(0); | ||||||
|  | 
 | ||||||
|  | void setup() { | ||||||
|  |   // put your setup code here, to run once:
 | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   delay(1000); | ||||||
|  |   Serial.println("Start setup"); | ||||||
|  |   adc.begin(); | ||||||
|  |   adc.setAdcSetting(adcSetting); | ||||||
|  |   //measureUnit.setGlobalTempOffset(-17);
 | ||||||
|  |   Serial.println("End setup"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void loop() { | ||||||
|  |   // put your main code here, to run repeatedly:
 | ||||||
|  |   adc.startSample(channel); | ||||||
|  | 
 | ||||||
|  |   if(adc.isSampleReady()) | ||||||
|  |   { | ||||||
|  |     Serial.print("Sample is ready : ");Serial.println(channel); | ||||||
|  |     double raw = adc.getSampleValue(); | ||||||
|  |     Serial.print("Value : ");Serial.println(raw,4); | ||||||
|  |     Serial.print("Voltage : ");Serial.println(raw * adc.getQuantum()); | ||||||
|  |     Serial.println(); | ||||||
|  | 
 | ||||||
|  |     channel++; | ||||||
|  |     channel %= 8; | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user