Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SDI12_device.h@7:1f506c65c4e8, 2018-08-01 (annotated)
- Committer:
- amateusz
- Date:
- Wed Aug 01 17:29:51 2018 +0000
- Revision:
- 7:1f506c65c4e8
- Parent:
- 6:d9a5240a99fd
- Child:
- 8:1beed160ed13
changed logic. finally works without goto (sic!)
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:d58ebb2bed9a | 25 | static int detect(SDI12 &sdi12, char indices[]) { |
amateusz | 0:d58ebb2bed9a | 26 | char found = 0; |
amateusz | 5:e53104570fde | 27 | for (size_t i = 0; i < ADDRRICES.size(); ++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 | 7:1f506c65c4e8 | 33 | debug("SEARCHING: %d\r\n", i); |
amateusz | 0:d58ebb2bed9a | 34 | Timer detectTimer; |
amateusz | 0:d58ebb2bed9a | 35 | detectTimer.start(); |
amateusz | 7:1f506c65c4e8 | 36 | while (detectTimer.read_ms() < RESPONSE_TIMEOUT) { |
amateusz | 5:e53104570fde | 37 | if (sdi12.RxInProgress()) detectTimer.reset(); |
amateusz | 7:1f506c65c4e8 | 38 | if (sdi12.RxBufferAvailable()) { |
amateusz | 7:1f506c65c4e8 | 39 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 7:1f506c65c4e8 | 40 | char buffer[bufferSize]; |
amateusz | 7:1f506c65c4e8 | 41 | sdi12.getRxBuffer(buffer); |
amateusz | 7:1f506c65c4e8 | 42 | // if first char is valid address char |
amateusz | 7:1f506c65c4e8 | 43 | if (ADDRRICES.find(buffer[0])) { |
amateusz | 5:e53104570fde | 44 | // if (buffer[0] >= '0' && buffer[0] <= '9' || |
amateusz | 5:e53104570fde | 45 | // buffer[0] >= 'a' && buffer[0] <= 'z' || |
amateusz | 5:e53104570fde | 46 | // buffer[0] >= 'A' && buffer[0] <= 'Z') { |
amateusz | 7:1f506c65c4e8 | 47 | indices[found++] = buffer[0]; |
amateusz | 7:1f506c65c4e8 | 48 | debug("FOUND: %d -> %c\r\n", i, indices[found-1]); |
amateusz | 7:1f506c65c4e8 | 49 | } |
amateusz | 7:1f506c65c4e8 | 50 | |
amateusz | 7:1f506c65c4e8 | 51 | } |
amateusz | 0:d58ebb2bed9a | 52 | } |
amateusz | 7:1f506c65c4e8 | 53 | |
amateusz | 0:d58ebb2bed9a | 54 | } |
amateusz | 0:d58ebb2bed9a | 55 | return found; |
amateusz | 0:d58ebb2bed9a | 56 | }; |
amateusz | 0:d58ebb2bed9a | 57 | |
amateusz | 2:e2db05bc4708 | 58 | SDI12_device (SDI12 &inst, char address, EventQueue &mainDispatcher) : _sdi12(inst) { |
amateusz | 0:d58ebb2bed9a | 59 | setAddress(address); |
amateusz | 2:e2db05bc4708 | 60 | sensorQueue.chain(&mainDispatcher); |
amateusz | 1:6b1a21925a81 | 61 | if(getIdentification(_ident_struct)); |
amateusz | 0:d58ebb2bed9a | 62 | }; |
amateusz | 5:e53104570fde | 63 | ~SDI12_device () { |
amateusz | 5:e53104570fde | 64 | // unchain event queue |
amateusz | 5:e53104570fde | 65 | sensorQueue.cancel(_measurementEventId); |
amateusz | 5:e53104570fde | 66 | sensorQueue.chain(NULL); |
amateusz | 5:e53104570fde | 67 | } |
amateusz | 0:d58ebb2bed9a | 68 | |
amateusz | 0:d58ebb2bed9a | 69 | // void printIdentification(){ |
amateusz | 0:d58ebb2bed9a | 70 | // Serial.println(_ident_struct.company); |
amateusz | 0:d58ebb2bed9a | 71 | // Serial.println(_ident_struct.model); |
amateusz | 0:d58ebb2bed9a | 72 | // Serial.println(_ident_struct.version); |
amateusz | 0:d58ebb2bed9a | 73 | // } |
amateusz | 0:d58ebb2bed9a | 74 | // |
amateusz | 2:e2db05bc4708 | 75 | |
amateusz | 0:d58ebb2bed9a | 76 | // // returns after how many seconds a measurement will be ready |
amateusz | 2:e2db05bc4708 | 77 | int measure(bool concurrent = true) { |
amateusz | 4:11438803516c | 78 | |
amateusz | 2:e2db05bc4708 | 79 | std::string question = string("?") + string(concurrent?"C":"M") + string("!"); |
amateusz | 2:e2db05bc4708 | 80 | question[0] = _address; |
amateusz | 2:e2db05bc4708 | 81 | _sdi12.sendCommand(question); |
amateusz | 2:e2db05bc4708 | 82 | |
amateusz | 2:e2db05bc4708 | 83 | Timer timeout; |
amateusz | 2:e2db05bc4708 | 84 | timeout.start(); |
amateusz | 2:e2db05bc4708 | 85 | while (sdi12.RxBufferAvailable() == 0) { |
amateusz | 2:e2db05bc4708 | 86 | if (sdi12.RxInProgress()) timeout.reset(); |
amateusz | 5:e53104570fde | 87 | if(timeout.read_ms() > RESPONSE_TIMEOUT) { |
amateusz | 2:e2db05bc4708 | 88 | return false; |
amateusz | 2:e2db05bc4708 | 89 | } |
amateusz | 2:e2db05bc4708 | 90 | } |
amateusz | 2:e2db05bc4708 | 91 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 2:e2db05bc4708 | 92 | char buffer[bufferSize+1]; |
amateusz | 2:e2db05bc4708 | 93 | sdi12.getRxBuffer(buffer); |
amateusz | 2:e2db05bc4708 | 94 | buffer[bufferSize] = '\0'; |
amateusz | 2:e2db05bc4708 | 95 | std::string response(buffer); |
amateusz | 2:e2db05bc4708 | 96 | |
amateusz | 2:e2db05bc4708 | 97 | if (response[0] == _address) { |
amateusz | 2:e2db05bc4708 | 98 | char measurementsCount = std::atoi(response.substr(1+3,(concurrent?2:1)).c_str()); |
amateusz | 2:e2db05bc4708 | 99 | char waitFor = std::atoi(response.substr(1,3).c_str()); |
amateusz | 2:e2db05bc4708 | 100 | _measurement.count = measurementsCount; |
amateusz | 4:11438803516c | 101 | _measurement.readyIn = waitFor; |
amateusz | 2:e2db05bc4708 | 102 | // _measurement.timestampMeasurementReadyAt |
amateusz | 2:e2db05bc4708 | 103 | debug("wait for %d measurement for %d seconds...", _measurement.count, waitFor); |
amateusz | 5:e53104570fde | 104 | _measurementEventId = sensorQueue.call_in(waitFor * 1000, callback(this, &SDI12_device::read)); |
amateusz | 5:e53104570fde | 105 | debug("measurement scheduled"); |
amateusz | 4:11438803516c | 106 | // if (_measurement.values != NULL) delete[] _measurement.values; |
amateusz | 4:11438803516c | 107 | // _measurement.values = new float[measurementsCount]; |
amateusz | 2:e2db05bc4708 | 108 | return 0; |
amateusz | 2:e2db05bc4708 | 109 | } |
amateusz | 2:e2db05bc4708 | 110 | return -1; |
amateusz | 2:e2db05bc4708 | 111 | }; |
amateusz | 0:d58ebb2bed9a | 112 | // |
amateusz | 0:d58ebb2bed9a | 113 | // bool isMeasurementReady(){ |
amateusz | 0:d58ebb2bed9a | 114 | // return (((unsigned)(_measurement.timestampMeasurementReadyAt - millis())>0)?false:true); |
amateusz | 0:d58ebb2bed9a | 115 | // }; |
amateusz | 0:d58ebb2bed9a | 116 | // |
amateusz | 0:d58ebb2bed9a | 117 | // short unsigned int measurementReadyIn(){ // ms |
amateusz | 0:d58ebb2bed9a | 118 | // if (isMeasurementReady()) |
amateusz | 0:d58ebb2bed9a | 119 | // return 0; |
amateusz | 0:d58ebb2bed9a | 120 | // else{ |
amateusz | 0:d58ebb2bed9a | 121 | // return _measurement.timestampMeasurementReadyAt - millis(); |
amateusz | 0:d58ebb2bed9a | 122 | // } |
amateusz | 0:d58ebb2bed9a | 123 | // }; |
amateusz | 0:d58ebb2bed9a | 124 | // |
amateusz | 4:11438803516c | 125 | char readyIn() { |
amateusz | 4:11438803516c | 126 | return _measurement.readyIn; |
amateusz | 4:11438803516c | 127 | } |
amateusz | 4:11438803516c | 128 | |
amateusz | 2:e2db05bc4708 | 129 | bool read() { |
amateusz | 3:2847f7c543d3 | 130 | char valuesAlreadyRead = 0; |
amateusz | 2:e2db05bc4708 | 131 | std::string question = string("?") + string("D0") + string("!"); |
amateusz | 2:e2db05bc4708 | 132 | question[0] = _address; |
amateusz | 2:e2db05bc4708 | 133 | _sdi12.sendCommand(question); |
amateusz | 2:e2db05bc4708 | 134 | |
amateusz | 2:e2db05bc4708 | 135 | Timer timeout; |
amateusz | 2:e2db05bc4708 | 136 | timeout.start(); |
amateusz | 2:e2db05bc4708 | 137 | while (sdi12.RxBufferAvailable() == 0) { |
amateusz | 2:e2db05bc4708 | 138 | if (sdi12.RxInProgress()) timeout.reset(); |
amateusz | 5:e53104570fde | 139 | if(timeout.read_ms() > RESPONSE_TIMEOUT) { |
amateusz | 2:e2db05bc4708 | 140 | return false; |
amateusz | 2:e2db05bc4708 | 141 | } |
amateusz | 2:e2db05bc4708 | 142 | } |
amateusz | 2:e2db05bc4708 | 143 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 2:e2db05bc4708 | 144 | char buffer[bufferSize+1]; |
amateusz | 2:e2db05bc4708 | 145 | sdi12.getRxBuffer(buffer); |
amateusz | 2:e2db05bc4708 | 146 | buffer[bufferSize] = '\0'; |
amateusz | 2:e2db05bc4708 | 147 | std::string response(buffer); |
amateusz | 2:e2db05bc4708 | 148 | |
amateusz | 4:11438803516c | 149 | // debug("parser. recv: %s\r\n", response); |
amateusz | 3:2847f7c543d3 | 150 | if (response[0] == _address) { |
amateusz | 3:2847f7c543d3 | 151 | // parser here |
amateusz | 3:2847f7c543d3 | 152 | response = response.substr(1); // to limit repeting this operation later. i.e. extract only values e.g. +21.3-123+123 |
amateusz | 3:2847f7c543d3 | 153 | // the only two possible delimeters of a value |
amateusz | 3:2847f7c543d3 | 154 | size_t next_start_index = response.find_first_of("-+", 0); |
amateusz | 3:2847f7c543d3 | 155 | size_t next_end_index; |
amateusz | 3:2847f7c543d3 | 156 | // ready, steady, parse!! |
amateusz | 3:2847f7c543d3 | 157 | while(next_start_index != std::string::npos) { |
amateusz | 3:2847f7c543d3 | 158 | // determine start index: |
amateusz | 3:2847f7c543d3 | 159 | next_end_index = response.find_first_of("-+", next_start_index + 1); // std::substr is prepared to take std::npos |
amateusz | 3:2847f7c543d3 | 160 | float value = std::atof(response.substr(next_start_index, next_end_index).c_str()); |
amateusz | 4:11438803516c | 161 | // debug("parsed: %f\r\n", value); |
amateusz | 4:11438803516c | 162 | _measurement.values[valuesAlreadyRead++] = value; |
amateusz | 3:2847f7c543d3 | 163 | next_start_index = response.find_first_of("-+", next_end_index); |
amateusz | 3:2847f7c543d3 | 164 | } |
amateusz | 3:2847f7c543d3 | 165 | } |
amateusz | 4:11438803516c | 166 | return true; |
amateusz | 2:e2db05bc4708 | 167 | } |
amateusz | 4:11438803516c | 168 | |
amateusz | 4:11438803516c | 169 | |
amateusz | 0:d58ebb2bed9a | 170 | // |
amateusz | 4:11438803516c | 171 | const unsigned char getMeasurementCount() { |
amateusz | 2:e2db05bc4708 | 172 | return _measurement.count; |
amateusz | 2:e2db05bc4708 | 173 | } |
amateusz | 2:e2db05bc4708 | 174 | |
amateusz | 4:11438803516c | 175 | const float getMeasurementValue(char which) { |
amateusz | 2:e2db05bc4708 | 176 | return _measurement.values[which]; |
amateusz | 2:e2db05bc4708 | 177 | } |
amateusz | 2:e2db05bc4708 | 178 | |
amateusz | 0:d58ebb2bed9a | 179 | void setAddress(char address) { |
amateusz | 0:d58ebb2bed9a | 180 | _address = address; |
amateusz | 0:d58ebb2bed9a | 181 | }; |
amateusz | 0:d58ebb2bed9a | 182 | // |
amateusz | 0:d58ebb2bed9a | 183 | // |
amateusz | 0:d58ebb2bed9a | 184 | private: |
amateusz | 5:e53104570fde | 185 | static const int RESPONSE_TIMEOUT = 15+1; // ms |
amateusz | 5:e53104570fde | 186 | static const std::string ADDRRICES; // as in index -> indices, |
amateusz | 5:e53104570fde | 187 | |
amateusz | 0:d58ebb2bed9a | 188 | SDI12 &_sdi12; |
amateusz | 0:d58ebb2bed9a | 189 | char _address; |
amateusz | 5:e53104570fde | 190 | int _measurementEventId; |
amateusz | 0:d58ebb2bed9a | 191 | Measurement_struct _measurement; |
amateusz | 0:d58ebb2bed9a | 192 | |
amateusz | 2:e2db05bc4708 | 193 | EventQueue sensorQueue; |
amateusz | 2:e2db05bc4708 | 194 | |
amateusz | 1:6b1a21925a81 | 195 | bool getIdentification(Identification_struct &ident) { |
amateusz | 1:6b1a21925a81 | 196 | // _sdi12.sendCommand(std::string(_address) + "I!"); |
amateusz | 1:6b1a21925a81 | 197 | std::string question = "?I!"; |
amateusz | 1:6b1a21925a81 | 198 | question[0] = _address; |
amateusz | 1:6b1a21925a81 | 199 | _sdi12.sendCommand(question); |
amateusz | 0:d58ebb2bed9a | 200 | |
amateusz | 1:6b1a21925a81 | 201 | Timer timeout; |
amateusz | 1:6b1a21925a81 | 202 | timeout.start(); |
amateusz | 1:6b1a21925a81 | 203 | while (sdi12.RxBufferAvailable() == 0) { |
amateusz | 1:6b1a21925a81 | 204 | if (sdi12.RxInProgress()) timeout.reset(); |
amateusz | 5:e53104570fde | 205 | if(timeout.read_ms() > RESPONSE_TIMEOUT) { |
amateusz | 1:6b1a21925a81 | 206 | return false; |
amateusz | 1:6b1a21925a81 | 207 | } |
amateusz | 1:6b1a21925a81 | 208 | } |
amateusz | 1:6b1a21925a81 | 209 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 1:6b1a21925a81 | 210 | char buffer[bufferSize+1]; |
amateusz | 1:6b1a21925a81 | 211 | sdi12.getRxBuffer(buffer); |
amateusz | 1:6b1a21925a81 | 212 | buffer[bufferSize] = '\0'; |
amateusz | 1:6b1a21925a81 | 213 | std::string response(buffer); |
amateusz | 0:d58ebb2bed9a | 214 | |
amateusz | 1:6b1a21925a81 | 215 | if (response[0] == _address) { |
amateusz | 1:6b1a21925a81 | 216 | // e.g.: 113DECAGON GS3 402 |
amateusz | 2:e2db05bc4708 | 217 | |
amateusz | 1:6b1a21925a81 | 218 | ident.sdi_version = std::atoi(response.substr(1, 2).c_str()); |
amateusz | 1:6b1a21925a81 | 219 | std::string tempStr = response.substr(3, 8); |
amateusz | 1:6b1a21925a81 | 220 | strcpy(ident.company, tempStr.c_str()); |
amateusz | 1:6b1a21925a81 | 221 | |
amateusz | 1:6b1a21925a81 | 222 | tempStr = response.substr(3+8, 6); |
amateusz | 1:6b1a21925a81 | 223 | strcpy(ident.model, tempStr.c_str()); |
amateusz | 1:6b1a21925a81 | 224 | |
amateusz | 1:6b1a21925a81 | 225 | tempStr = response.substr(3+8+6, 3); |
amateusz | 1:6b1a21925a81 | 226 | strcpy(ident.version, tempStr.c_str()); |
amateusz | 1:6b1a21925a81 | 227 | return true; |
amateusz | 0:d58ebb2bed9a | 228 | } |
amateusz | 1:6b1a21925a81 | 229 | return false; |
amateusz | 1:6b1a21925a81 | 230 | } |
amateusz | 0:d58ebb2bed9a | 231 | |
amateusz | 5:e53104570fde | 232 | }; |
amateusz | 5:e53104570fde | 233 | |
amateusz | 5:e53104570fde | 234 | const std::string SDI12_device::ADDRRICES = "0123456789abcdefgijklmnoprstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ"; |