Mateusz Grzywacz / SDI12_device
Committer:
amateusz
Date:
Thu Aug 02 16:58:58 2018 +0000
Revision:
12:270bb5b69e05
Parent:
11:e0ccc1072c42
Child:
13:0093792f2325
added delay to scheduled readout. better to be later than too early in this case

Who changed what in which revision?

UserRevisionLine numberNew contents of line
amateusz 0:d58ebb2bed9a 1 #include "SDI12.h"
amateusz 0:d58ebb2bed9a 2 #include <string>
amateusz 2:e2db05bc4708 3 #include "mbed.h"
amateusz 0:d58ebb2bed9a 4
amateusz 0:d58ebb2bed9a 5 class SDI12_device
amateusz 0:d58ebb2bed9a 6 {
amateusz 0:d58ebb2bed9a 7 public:
amateusz 0:d58ebb2bed9a 8 struct Identification_struct {
amateusz 0:d58ebb2bed9a 9 unsigned char sdi_version;
amateusz 0:d58ebb2bed9a 10 char company[8+1];
amateusz 0:d58ebb2bed9a 11 char model[6+1];
amateusz 0:d58ebb2bed9a 12 char version[3+1];
amateusz 0:d58ebb2bed9a 13 };
amateusz 0:d58ebb2bed9a 14
amateusz 0:d58ebb2bed9a 15 struct Measurement_struct {
amateusz 0:d58ebb2bed9a 16 unsigned long timestampMeasurementReadyAt;
amateusz 4:11438803516c 17 char readyIn;
amateusz 0:d58ebb2bed9a 18 bool _measurementAlreadyRead;
amateusz 0:d58ebb2bed9a 19 char count;
amateusz 4:11438803516c 20 float values[48]; // not float values [] !! :O
amateusz 0:d58ebb2bed9a 21 };
amateusz 0:d58ebb2bed9a 22
amateusz 0:d58ebb2bed9a 23 Identification_struct _ident_struct;
amateusz 0:d58ebb2bed9a 24
amateusz 10:efd1e313fe8c 25 static int detect(SDI12 &sdi12, char indices[], int stop = -1, int start = -1) {
amateusz 0:d58ebb2bed9a 26 char found = 0;
amateusz 10:efd1e313fe8c 27 for (size_t i = (start==-1?0:start); i < (stop==-1?ADDRRICES.size():stop+1); ++i) {
amateusz 7:1f506c65c4e8 28
amateusz 0:d58ebb2bed9a 29 string question = "?!";
amateusz 5:e53104570fde 30 question[0] = ADDRRICES[i];
amateusz 0:d58ebb2bed9a 31 sdi12.sendCommand(question);
amateusz 0:d58ebb2bed9a 32 std::string response;
amateusz 0:d58ebb2bed9a 33 Timer detectTimer;
amateusz 0:d58ebb2bed9a 34 detectTimer.start();
amateusz 7:1f506c65c4e8 35 while (detectTimer.read_ms() < RESPONSE_TIMEOUT) {
amateusz 5:e53104570fde 36 if (sdi12.RxInProgress()) detectTimer.reset();
amateusz 7:1f506c65c4e8 37 if (sdi12.RxBufferAvailable()) {
amateusz 7:1f506c65c4e8 38 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 7:1f506c65c4e8 39 char buffer[bufferSize];
amateusz 7:1f506c65c4e8 40 sdi12.getRxBuffer(buffer);
amateusz 7:1f506c65c4e8 41 // if first char is valid address char
amateusz 7:1f506c65c4e8 42 if (ADDRRICES.find(buffer[0])) {
amateusz 7:1f506c65c4e8 43 indices[found++] = buffer[0];
amateusz 8:1beed160ed13 44 // debug("FOUND: %d -> %c\r\n", i, indices[found-1]);
amateusz 7:1f506c65c4e8 45 }
amateusz 7:1f506c65c4e8 46 }
amateusz 0:d58ebb2bed9a 47 }
amateusz 10:efd1e313fe8c 48 osDelay(200);
amateusz 0:d58ebb2bed9a 49 }
amateusz 0:d58ebb2bed9a 50 return found;
amateusz 0:d58ebb2bed9a 51 };
amateusz 0:d58ebb2bed9a 52
amateusz 10:efd1e313fe8c 53 SDI12_device (SDI12 &inst, char address, EventQueue &mainDispatcher) : _sdi12(inst),sensorQueue(4*EVENTS_QUEUE_SIZE) {
amateusz 0:d58ebb2bed9a 54 setAddress(address);
amateusz 2:e2db05bc4708 55 sensorQueue.chain(&mainDispatcher);
amateusz 1:6b1a21925a81 56 if(getIdentification(_ident_struct));
amateusz 0:d58ebb2bed9a 57 };
amateusz 10:efd1e313fe8c 58 ~SDI12_device () {
amateusz 10:efd1e313fe8c 59 // unchain event queue
amateusz 9:a3062b9e4324 60 // sensorQueue.cancel(_measurementEventId);
amateusz 10:efd1e313fe8c 61 sensorQueue.chain(NULL);
amateusz 10:efd1e313fe8c 62 }
amateusz 0:d58ebb2bed9a 63
amateusz 2:e2db05bc4708 64
amateusz 0:d58ebb2bed9a 65 // // returns after how many seconds a measurement will be ready
amateusz 2:e2db05bc4708 66 int measure(bool concurrent = true) {
amateusz 4:11438803516c 67
amateusz 2:e2db05bc4708 68 std::string question = string("?") + string(concurrent?"C":"M") + string("!");
amateusz 2:e2db05bc4708 69 question[0] = _address;
amateusz 2:e2db05bc4708 70 _sdi12.sendCommand(question);
amateusz 2:e2db05bc4708 71
amateusz 2:e2db05bc4708 72 Timer timeout;
amateusz 2:e2db05bc4708 73 timeout.start();
amateusz 2:e2db05bc4708 74 while (sdi12.RxBufferAvailable() == 0) {
amateusz 2:e2db05bc4708 75 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 76 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 2:e2db05bc4708 77 return false;
amateusz 2:e2db05bc4708 78 }
amateusz 2:e2db05bc4708 79 }
amateusz 10:efd1e313fe8c 80
amateusz 2:e2db05bc4708 81 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 2:e2db05bc4708 82 char buffer[bufferSize+1];
amateusz 2:e2db05bc4708 83 sdi12.getRxBuffer(buffer);
amateusz 2:e2db05bc4708 84 buffer[bufferSize] = '\0';
amateusz 2:e2db05bc4708 85 std::string response(buffer);
amateusz 2:e2db05bc4708 86
amateusz 2:e2db05bc4708 87 if (response[0] == _address) {
amateusz 2:e2db05bc4708 88 char measurementsCount = std::atoi(response.substr(1+3,(concurrent?2:1)).c_str());
amateusz 2:e2db05bc4708 89 char waitFor = std::atoi(response.substr(1,3).c_str());
amateusz 2:e2db05bc4708 90 _measurement.count = measurementsCount;
amateusz 4:11438803516c 91 _measurement.readyIn = waitFor;
amateusz 2:e2db05bc4708 92 // _measurement.timestampMeasurementReadyAt
amateusz 2:e2db05bc4708 93 debug("wait for %d measurement for %d seconds...", _measurement.count, waitFor);
amateusz 11:e0ccc1072c42 94 _valuesReadyCount = 0;
amateusz 12:270bb5b69e05 95 _measurementEventId = sensorQueue.call_in(waitFor * 1000 + 300, callback(this, &SDI12_device::read), '0'); // for good measure, not to be too early
amateusz 9:a3062b9e4324 96 // debug("measurement scheduled");
amateusz 4:11438803516c 97 // if (_measurement.values != NULL) delete[] _measurement.values;
amateusz 4:11438803516c 98 // _measurement.values = new float[measurementsCount];
amateusz 2:e2db05bc4708 99 return 0;
amateusz 2:e2db05bc4708 100 }
amateusz 2:e2db05bc4708 101 return -1;
amateusz 2:e2db05bc4708 102 };
amateusz 0:d58ebb2bed9a 103 //
amateusz 0:d58ebb2bed9a 104 // bool isMeasurementReady(){
amateusz 0:d58ebb2bed9a 105 // return (((unsigned)(_measurement.timestampMeasurementReadyAt - millis())>0)?false:true);
amateusz 0:d58ebb2bed9a 106 // };
amateusz 0:d58ebb2bed9a 107 //
amateusz 0:d58ebb2bed9a 108 // short unsigned int measurementReadyIn(){ // ms
amateusz 0:d58ebb2bed9a 109 // if (isMeasurementReady())
amateusz 0:d58ebb2bed9a 110 // return 0;
amateusz 0:d58ebb2bed9a 111 // else{
amateusz 0:d58ebb2bed9a 112 // return _measurement.timestampMeasurementReadyAt - millis();
amateusz 0:d58ebb2bed9a 113 // }
amateusz 0:d58ebb2bed9a 114 // };
amateusz 0:d58ebb2bed9a 115 //
amateusz 4:11438803516c 116 char readyIn() {
amateusz 4:11438803516c 117 return _measurement.readyIn;
amateusz 4:11438803516c 118 }
amateusz 4:11438803516c 119
amateusz 11:e0ccc1072c42 120 bool read(char group = '0') {
amateusz 11:e0ccc1072c42 121 // Measurement (M), Continuous (R), and Concurrent (C) commands and subsequent Data (D)
amateusz 11:e0ccc1072c42 122 std::string question = std::string("?") + std::string("D") + std::string(1,group)+ std::string("!");
amateusz 2:e2db05bc4708 123 question[0] = _address;
amateusz 2:e2db05bc4708 124 _sdi12.sendCommand(question);
amateusz 2:e2db05bc4708 125
amateusz 2:e2db05bc4708 126 Timer timeout;
amateusz 2:e2db05bc4708 127 timeout.start();
amateusz 2:e2db05bc4708 128 while (sdi12.RxBufferAvailable() == 0) {
amateusz 2:e2db05bc4708 129 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 130 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 2:e2db05bc4708 131 return false;
amateusz 2:e2db05bc4708 132 }
amateusz 2:e2db05bc4708 133 }
amateusz 2:e2db05bc4708 134 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 2:e2db05bc4708 135 char buffer[bufferSize+1];
amateusz 2:e2db05bc4708 136 sdi12.getRxBuffer(buffer);
amateusz 2:e2db05bc4708 137 buffer[bufferSize] = '\0';
amateusz 2:e2db05bc4708 138 std::string response(buffer);
amateusz 2:e2db05bc4708 139
amateusz 4:11438803516c 140 // debug("parser. recv: %s\r\n", response);
amateusz 3:2847f7c543d3 141 if (response[0] == _address) {
amateusz 3:2847f7c543d3 142 // parser here
amateusz 3:2847f7c543d3 143 response = response.substr(1); // to limit repeting this operation later. i.e. extract only values e.g. +21.3-123+123
amateusz 3:2847f7c543d3 144 // the only two possible delimeters of a value
amateusz 3:2847f7c543d3 145 size_t next_start_index = response.find_first_of("-+", 0);
amateusz 3:2847f7c543d3 146 size_t next_end_index;
amateusz 3:2847f7c543d3 147 // ready, steady, parse!!
amateusz 3:2847f7c543d3 148 while(next_start_index != std::string::npos) {
amateusz 3:2847f7c543d3 149 // determine start index:
amateusz 3:2847f7c543d3 150 next_end_index = response.find_first_of("-+", next_start_index + 1); // std::substr is prepared to take std::npos
amateusz 3:2847f7c543d3 151 float value = std::atof(response.substr(next_start_index, next_end_index).c_str());
amateusz 4:11438803516c 152 // debug("parsed: %f\r\n", value);
amateusz 11:e0ccc1072c42 153 _measurement.values[_valuesReadyCount++] = value;
amateusz 3:2847f7c543d3 154 next_start_index = response.find_first_of("-+", next_end_index);
amateusz 3:2847f7c543d3 155 }
amateusz 11:e0ccc1072c42 156 // if current parsing doesn't return all the expexted measurements, then press harder and poll further Dx commands. RECURSION HERE *.*
amateusz 11:e0ccc1072c42 157 if (_valuesReadyCount < _measurement.count)
amateusz 11:e0ccc1072c42 158 read(group + 1);
amateusz 3:2847f7c543d3 159 }
amateusz 4:11438803516c 160 return true;
amateusz 2:e2db05bc4708 161 }
amateusz 4:11438803516c 162
amateusz 4:11438803516c 163
amateusz 0:d58ebb2bed9a 164 //
amateusz 4:11438803516c 165 const unsigned char getMeasurementCount() {
amateusz 2:e2db05bc4708 166 return _measurement.count;
amateusz 2:e2db05bc4708 167 }
amateusz 2:e2db05bc4708 168
amateusz 4:11438803516c 169 const float getMeasurementValue(char which) {
amateusz 2:e2db05bc4708 170 return _measurement.values[which];
amateusz 2:e2db05bc4708 171 }
amateusz 2:e2db05bc4708 172
amateusz 0:d58ebb2bed9a 173 void setAddress(char address) {
amateusz 0:d58ebb2bed9a 174 _address = address;
amateusz 0:d58ebb2bed9a 175 };
amateusz 0:d58ebb2bed9a 176 //
amateusz 0:d58ebb2bed9a 177 //
amateusz 0:d58ebb2bed9a 178 private:
amateusz 5:e53104570fde 179 static const int RESPONSE_TIMEOUT = 15+1; // ms
amateusz 5:e53104570fde 180 static const std::string ADDRRICES; // as in index -> indices,
amateusz 5:e53104570fde 181
amateusz 0:d58ebb2bed9a 182 SDI12 &_sdi12;
amateusz 0:d58ebb2bed9a 183 char _address;
amateusz 5:e53104570fde 184 int _measurementEventId;
amateusz 0:d58ebb2bed9a 185 Measurement_struct _measurement;
amateusz 11:e0ccc1072c42 186 size_t _valuesReadyCount;
amateusz 0:d58ebb2bed9a 187
amateusz 2:e2db05bc4708 188 EventQueue sensorQueue;
amateusz 2:e2db05bc4708 189
amateusz 1:6b1a21925a81 190 bool getIdentification(Identification_struct &ident) {
amateusz 1:6b1a21925a81 191 // _sdi12.sendCommand(std::string(_address) + "I!");
amateusz 1:6b1a21925a81 192 std::string question = "?I!";
amateusz 1:6b1a21925a81 193 question[0] = _address;
amateusz 1:6b1a21925a81 194 _sdi12.sendCommand(question);
amateusz 0:d58ebb2bed9a 195
amateusz 1:6b1a21925a81 196 Timer timeout;
amateusz 1:6b1a21925a81 197 timeout.start();
amateusz 1:6b1a21925a81 198 while (sdi12.RxBufferAvailable() == 0) {
amateusz 1:6b1a21925a81 199 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 200 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 1:6b1a21925a81 201 return false;
amateusz 1:6b1a21925a81 202 }
amateusz 1:6b1a21925a81 203 }
amateusz 1:6b1a21925a81 204 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 1:6b1a21925a81 205 char buffer[bufferSize+1];
amateusz 1:6b1a21925a81 206 sdi12.getRxBuffer(buffer);
amateusz 1:6b1a21925a81 207 buffer[bufferSize] = '\0';
amateusz 1:6b1a21925a81 208 std::string response(buffer);
amateusz 0:d58ebb2bed9a 209
amateusz 1:6b1a21925a81 210 if (response[0] == _address) {
amateusz 1:6b1a21925a81 211 // e.g.: 113DECAGON GS3 402
amateusz 2:e2db05bc4708 212
amateusz 1:6b1a21925a81 213 ident.sdi_version = std::atoi(response.substr(1, 2).c_str());
amateusz 1:6b1a21925a81 214 std::string tempStr = response.substr(3, 8);
amateusz 1:6b1a21925a81 215 strcpy(ident.company, tempStr.c_str());
amateusz 1:6b1a21925a81 216
amateusz 1:6b1a21925a81 217 tempStr = response.substr(3+8, 6);
amateusz 1:6b1a21925a81 218 strcpy(ident.model, tempStr.c_str());
amateusz 1:6b1a21925a81 219
amateusz 1:6b1a21925a81 220 tempStr = response.substr(3+8+6, 3);
amateusz 1:6b1a21925a81 221 strcpy(ident.version, tempStr.c_str());
amateusz 1:6b1a21925a81 222 return true;
amateusz 0:d58ebb2bed9a 223 }
amateusz 1:6b1a21925a81 224 return false;
amateusz 1:6b1a21925a81 225 }
amateusz 0:d58ebb2bed9a 226
amateusz 5:e53104570fde 227 };
amateusz 5:e53104570fde 228
amateusz 5:e53104570fde 229 const std::string SDI12_device::ADDRRICES = "0123456789abcdefgijklmnoprstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ";