Mateusz Grzywacz / SDI12_device
Committer:
amateusz
Date:
Wed Aug 08 16:55:11 2018 +0000
Revision:
20:abccaaa16955
Parent:
19:a29b98ae0005
Child:
21:aa7b255c5896
more const strings!

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