Mateusz Grzywacz / SDI12_device
Committer:
amateusz
Date:
Mon Aug 06 17:43:24 2018 +0000
Revision:
16:44daef8babd6
Parent:
15:530bf2e09814
Child:
17:5cabfc047b40
deleted debug log

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 15:530bf2e09814 20 float * values; // 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 0:d58ebb2bed9a 28 string question = "?!";
amateusz 5:e53104570fde 29 question[0] = ADDRRICES[i];
amateusz 0:d58ebb2bed9a 30 sdi12.sendCommand(question);
amateusz 0:d58ebb2bed9a 31 std::string response;
amateusz 0:d58ebb2bed9a 32 Timer detectTimer;
amateusz 0:d58ebb2bed9a 33 detectTimer.start();
amateusz 15:530bf2e09814 34 while (detectTimer.read_ms() < RESPONSE_TIMEOUT * 4) {
amateusz 5:e53104570fde 35 if (sdi12.RxInProgress()) detectTimer.reset();
amateusz 7:1f506c65c4e8 36 if (sdi12.RxBufferAvailable()) {
amateusz 7:1f506c65c4e8 37 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 7:1f506c65c4e8 38 char buffer[bufferSize];
amateusz 7:1f506c65c4e8 39 sdi12.getRxBuffer(buffer);
amateusz 7:1f506c65c4e8 40 // if first char is valid address char
amateusz 7:1f506c65c4e8 41 if (ADDRRICES.find(buffer[0])) {
amateusz 7:1f506c65c4e8 42 indices[found++] = buffer[0];
amateusz 13:0093792f2325 43 debug("FOUND: %d -> %c\r\n", i, indices[found-1]);
amateusz 7:1f506c65c4e8 44 }
amateusz 7:1f506c65c4e8 45 }
amateusz 0:d58ebb2bed9a 46 }
amateusz 13:0093792f2325 47 osDelay(100);
amateusz 0:d58ebb2bed9a 48 }
amateusz 0:d58ebb2bed9a 49 return found;
amateusz 0:d58ebb2bed9a 50 };
amateusz 15:530bf2e09814 51
amateusz 15:530bf2e09814 52 SDI12_device(){
amateusz 15:530bf2e09814 53 debug("DEFAULT\r\n");
amateusz 15:530bf2e09814 54 }
amateusz 15:530bf2e09814 55
amateusz 15:530bf2e09814 56 SDI12_device (SDI12 *inst, char address, EventQueue &mainDispatcher) : _sdi12(inst) {
amateusz 15:530bf2e09814 57 sensorQueue = &EventQueue(4*EVENTS_QUEUE_SIZE);
amateusz 15:530bf2e09814 58 setAddress(address);
amateusz 15:530bf2e09814 59 parentQueue = &mainDispatcher;
amateusz 15:530bf2e09814 60 sensorQueue->chain(parentQueue);
amateusz 15:530bf2e09814 61 if(getIdentification(_ident_struct));
amateusz 15:530bf2e09814 62 };
amateusz 0:d58ebb2bed9a 63
amateusz 15:530bf2e09814 64 SDI12_device (SDI12 *inst, char address) : _sdi12(inst) {
amateusz 15:530bf2e09814 65 sensorQueue = NULL;
amateusz 0:d58ebb2bed9a 66 setAddress(address);
amateusz 15:530bf2e09814 67 parentQueue = NULL;
amateusz 1:6b1a21925a81 68 if(getIdentification(_ident_struct));
amateusz 0:d58ebb2bed9a 69 };
amateusz 15:530bf2e09814 70
amateusz 15:530bf2e09814 71
amateusz 15:530bf2e09814 72 SDI12_device & operator= (const SDI12_device & old) {
amateusz 15:530bf2e09814 73 _address = old._address;
amateusz 15:530bf2e09814 74 _ident_struct = old._ident_struct;
amateusz 15:530bf2e09814 75 // _sdi12 = old._sdi12; // non-copyable -.-
amateusz 15:530bf2e09814 76
amateusz 15:530bf2e09814 77 _measurementEventId = old._measurementEventId;
amateusz 15:530bf2e09814 78 _measurement = old._measurement;
amateusz 15:530bf2e09814 79 _valuesReadyCount = old._valuesReadyCount;
amateusz 15:530bf2e09814 80 _measurementReady = old._measurementReady;
amateusz 15:530bf2e09814 81
amateusz 15:530bf2e09814 82 parentQueue = old.parentQueue;
amateusz 15:530bf2e09814 83 sensorQueue = old.sensorQueue;
amateusz 15:530bf2e09814 84 }
amateusz 15:530bf2e09814 85
amateusz 10:efd1e313fe8c 86 ~SDI12_device () {
amateusz 15:530bf2e09814 87 delete [] _measurement.values;
amateusz 10:efd1e313fe8c 88 // unchain event queue
amateusz 9:a3062b9e4324 89 // sensorQueue.cancel(_measurementEventId);
amateusz 15:530bf2e09814 90 if (sensorQueue != NULL) sensorQueue->chain(NULL);
amateusz 15:530bf2e09814 91
amateusz 10:efd1e313fe8c 92 }
amateusz 0:d58ebb2bed9a 93
amateusz 15:530bf2e09814 94 // concurrent means that device under measurement won't signal its prempt readiness to the bus
amateusz 13:0093792f2325 95 int measure(bool concurrent = true, char group = '0') {
amateusz 4:11438803516c 96
amateusz 2:e2db05bc4708 97 std::string question = string("?") + string(concurrent?"C":"M") + string("!");
amateusz 2:e2db05bc4708 98 question[0] = _address;
amateusz 13:0093792f2325 99 if (group != '0')
amateusz 13:0093792f2325 100 question.insert(2, 1, group); // e.g. 2M! -> 2M1!
amateusz 15:530bf2e09814 101 _sdi12->sendCommand(question);
amateusz 2:e2db05bc4708 102
amateusz 2:e2db05bc4708 103 Timer timeout;
amateusz 2:e2db05bc4708 104 timeout.start();
amateusz 2:e2db05bc4708 105 while (sdi12.RxBufferAvailable() == 0) {
amateusz 2:e2db05bc4708 106 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 107 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 2:e2db05bc4708 108 return false;
amateusz 2:e2db05bc4708 109 }
amateusz 2:e2db05bc4708 110 }
amateusz 10:efd1e313fe8c 111
amateusz 2:e2db05bc4708 112 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 2:e2db05bc4708 113 char buffer[bufferSize+1];
amateusz 2:e2db05bc4708 114 sdi12.getRxBuffer(buffer);
amateusz 2:e2db05bc4708 115 buffer[bufferSize] = '\0';
amateusz 2:e2db05bc4708 116 std::string response(buffer);
amateusz 2:e2db05bc4708 117
amateusz 2:e2db05bc4708 118 if (response[0] == _address) {
amateusz 2:e2db05bc4708 119 char measurementsCount = std::atoi(response.substr(1+3,(concurrent?2:1)).c_str());
amateusz 2:e2db05bc4708 120 char waitFor = std::atoi(response.substr(1,3).c_str());
amateusz 2:e2db05bc4708 121 _measurement.count = measurementsCount;
amateusz 15:530bf2e09814 122 _measurement.values = new float[measurementsCount];
amateusz 4:11438803516c 123 _measurement.readyIn = waitFor;
amateusz 2:e2db05bc4708 124 // _measurement.timestampMeasurementReadyAt
amateusz 2:e2db05bc4708 125 debug("wait for %d measurement for %d seconds...", _measurement.count, waitFor);
amateusz 11:e0ccc1072c42 126 _valuesReadyCount = 0;
amateusz 13:0093792f2325 127 _measurementReady = false;
amateusz 15:530bf2e09814 128 if (parentQueue != NULL)
amateusz 15:530bf2e09814 129 _measurementEventId = sensorQueue->call_in(waitFor * 1000 + 500, callback(this, &SDI12_device::read), '0'); // + some [ms] for good measure, not to be too early
amateusz 9:a3062b9e4324 130 // debug("measurement scheduled");
amateusz 4:11438803516c 131 // if (_measurement.values != NULL) delete[] _measurement.values;
amateusz 4:11438803516c 132 // _measurement.values = new float[measurementsCount];
amateusz 2:e2db05bc4708 133 return 0;
amateusz 2:e2db05bc4708 134 }
amateusz 2:e2db05bc4708 135 return -1;
amateusz 2:e2db05bc4708 136 };
amateusz 13:0093792f2325 137
amateusz 4:11438803516c 138 char readyIn() {
amateusz 4:11438803516c 139 return _measurement.readyIn;
amateusz 4:11438803516c 140 }
amateusz 4:11438803516c 141
amateusz 13:0093792f2325 142 bool isReady() {
amateusz 13:0093792f2325 143 return _measurementReady;
amateusz 13:0093792f2325 144 }
amateusz 13:0093792f2325 145
amateusz 11:e0ccc1072c42 146 bool read(char group = '0') {
amateusz 11:e0ccc1072c42 147 // Measurement (M), Continuous (R), and Concurrent (C) commands and subsequent Data (D)
amateusz 11:e0ccc1072c42 148 std::string question = std::string("?") + std::string("D") + std::string(1,group)+ std::string("!");
amateusz 2:e2db05bc4708 149 question[0] = _address;
amateusz 15:530bf2e09814 150 _sdi12->sendCommand(question);
amateusz 2:e2db05bc4708 151
amateusz 2:e2db05bc4708 152 Timer timeout;
amateusz 2:e2db05bc4708 153 timeout.start();
amateusz 2:e2db05bc4708 154 while (sdi12.RxBufferAvailable() == 0) {
amateusz 2:e2db05bc4708 155 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 156 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 2:e2db05bc4708 157 return false;
amateusz 2:e2db05bc4708 158 }
amateusz 2:e2db05bc4708 159 }
amateusz 2:e2db05bc4708 160 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 2:e2db05bc4708 161 char buffer[bufferSize+1];
amateusz 2:e2db05bc4708 162 sdi12.getRxBuffer(buffer);
amateusz 2:e2db05bc4708 163 buffer[bufferSize] = '\0';
amateusz 2:e2db05bc4708 164 std::string response(buffer);
amateusz 2:e2db05bc4708 165
amateusz 4:11438803516c 166 // debug("parser. recv: %s\r\n", response);
amateusz 3:2847f7c543d3 167 if (response[0] == _address) {
amateusz 3:2847f7c543d3 168 // parser here
amateusz 3:2847f7c543d3 169 response = response.substr(1); // to limit repeting this operation later. i.e. extract only values e.g. +21.3-123+123
amateusz 3:2847f7c543d3 170 // the only two possible delimeters of a value
amateusz 3:2847f7c543d3 171 size_t next_start_index = response.find_first_of("-+", 0);
amateusz 3:2847f7c543d3 172 size_t next_end_index;
amateusz 3:2847f7c543d3 173 // ready, steady, parse!!
amateusz 3:2847f7c543d3 174 while(next_start_index != std::string::npos) {
amateusz 3:2847f7c543d3 175 // determine start index:
amateusz 3:2847f7c543d3 176 next_end_index = response.find_first_of("-+", next_start_index + 1); // std::substr is prepared to take std::npos
amateusz 15:530bf2e09814 177
amateusz 3:2847f7c543d3 178 float value = std::atof(response.substr(next_start_index, next_end_index).c_str());
amateusz 4:11438803516c 179 // debug("parsed: %f\r\n", value);
amateusz 11:e0ccc1072c42 180 _measurement.values[_valuesReadyCount++] = value;
amateusz 3:2847f7c543d3 181 next_start_index = response.find_first_of("-+", next_end_index);
amateusz 3:2847f7c543d3 182 }
amateusz 11:e0ccc1072c42 183 // if current parsing doesn't return all the expexted measurements, then press harder and poll further Dx commands. RECURSION HERE *.*
amateusz 11:e0ccc1072c42 184 if (_valuesReadyCount < _measurement.count)
amateusz 11:e0ccc1072c42 185 read(group + 1);
amateusz 13:0093792f2325 186 else {
amateusz 13:0093792f2325 187 _measurementReady = true;
amateusz 13:0093792f2325 188 }
amateusz 3:2847f7c543d3 189 }
amateusz 4:11438803516c 190 return true;
amateusz 2:e2db05bc4708 191 }
amateusz 4:11438803516c 192
amateusz 4:11438803516c 193
amateusz 0:d58ebb2bed9a 194 //
amateusz 4:11438803516c 195 const unsigned char getMeasurementCount() {
amateusz 2:e2db05bc4708 196 return _measurement.count;
amateusz 2:e2db05bc4708 197 }
amateusz 2:e2db05bc4708 198
amateusz 4:11438803516c 199 const float getMeasurementValue(char which) {
amateusz 13:0093792f2325 200 _measurementReady = false; // reading /any/ of the values resets this
amateusz 2:e2db05bc4708 201 return _measurement.values[which];
amateusz 2:e2db05bc4708 202 }
amateusz 2:e2db05bc4708 203
amateusz 0:d58ebb2bed9a 204 void setAddress(char address) {
amateusz 0:d58ebb2bed9a 205 _address = address;
amateusz 0:d58ebb2bed9a 206 };
amateusz 0:d58ebb2bed9a 207 //
amateusz 0:d58ebb2bed9a 208 //
amateusz 0:d58ebb2bed9a 209 private:
amateusz 13:0093792f2325 210 static const int RESPONSE_TIMEOUT = 15+1; // device should start to respond within [ms]
amateusz 5:e53104570fde 211 static const std::string ADDRRICES; // as in index -> indices,
amateusz 5:e53104570fde 212
amateusz 15:530bf2e09814 213 SDI12 *_sdi12;
amateusz 0:d58ebb2bed9a 214 char _address;
amateusz 5:e53104570fde 215 int _measurementEventId;
amateusz 0:d58ebb2bed9a 216 Measurement_struct _measurement;
amateusz 11:e0ccc1072c42 217 size_t _valuesReadyCount;
amateusz 13:0093792f2325 218 bool _measurementReady;
amateusz 0:d58ebb2bed9a 219
amateusz 15:530bf2e09814 220 EventQueue *parentQueue;
amateusz 15:530bf2e09814 221 EventQueue *sensorQueue;
amateusz 2:e2db05bc4708 222
amateusz 1:6b1a21925a81 223 bool getIdentification(Identification_struct &ident) {
amateusz 15:530bf2e09814 224 // _sdi12->sendCommand(std::string(_address) + "I!");
amateusz 1:6b1a21925a81 225 std::string question = "?I!";
amateusz 1:6b1a21925a81 226 question[0] = _address;
amateusz 15:530bf2e09814 227 _sdi12->sendCommand(question);
amateusz 0:d58ebb2bed9a 228
amateusz 1:6b1a21925a81 229 Timer timeout;
amateusz 1:6b1a21925a81 230 timeout.start();
amateusz 1:6b1a21925a81 231 while (sdi12.RxBufferAvailable() == 0) {
amateusz 1:6b1a21925a81 232 if (sdi12.RxInProgress()) timeout.reset();
amateusz 5:e53104570fde 233 if(timeout.read_ms() > RESPONSE_TIMEOUT) {
amateusz 1:6b1a21925a81 234 return false;
amateusz 1:6b1a21925a81 235 }
amateusz 1:6b1a21925a81 236 }
amateusz 1:6b1a21925a81 237 unsigned char bufferSize = sdi12.RxBufferAvailable();
amateusz 1:6b1a21925a81 238 char buffer[bufferSize+1];
amateusz 1:6b1a21925a81 239 sdi12.getRxBuffer(buffer);
amateusz 1:6b1a21925a81 240 buffer[bufferSize] = '\0';
amateusz 1:6b1a21925a81 241 std::string response(buffer);
amateusz 0:d58ebb2bed9a 242
amateusz 1:6b1a21925a81 243 if (response[0] == _address) {
amateusz 1:6b1a21925a81 244 // e.g.: 113DECAGON GS3 402
amateusz 2:e2db05bc4708 245
amateusz 1:6b1a21925a81 246 ident.sdi_version = std::atoi(response.substr(1, 2).c_str());
amateusz 1:6b1a21925a81 247 std::string tempStr = response.substr(3, 8);
amateusz 1:6b1a21925a81 248 strcpy(ident.company, tempStr.c_str());
amateusz 1:6b1a21925a81 249
amateusz 1:6b1a21925a81 250 tempStr = response.substr(3+8, 6);
amateusz 1:6b1a21925a81 251 strcpy(ident.model, tempStr.c_str());
amateusz 1:6b1a21925a81 252
amateusz 1:6b1a21925a81 253 tempStr = response.substr(3+8+6, 3);
amateusz 1:6b1a21925a81 254 strcpy(ident.version, tempStr.c_str());
amateusz 1:6b1a21925a81 255 return true;
amateusz 0:d58ebb2bed9a 256 }
amateusz 1:6b1a21925a81 257 return false;
amateusz 1:6b1a21925a81 258 }
amateusz 0:d58ebb2bed9a 259
amateusz 5:e53104570fde 260 };
amateusz 5:e53104570fde 261
amateusz 5:e53104570fde 262 const std::string SDI12_device::ADDRRICES = "0123456789abcdefgijklmnoprstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ";