Represents a single device. Take measurements, send commands. Needs SDI12 bus instance as argument. Allows to detect devices on the bus
SDI12_device.h@2:e2db05bc4708, 2018-07-27 (annotated)
- Committer:
- amateusz
- Date:
- Fri Jul 27 16:17:43 2018 +0000
- Revision:
- 2:e2db05bc4708
- Parent:
- 1:6b1a21925a81
- Child:
- 3:2847f7c543d3
adding eventqueue for every sensor to handle measuremnt ready
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 | 0:d58ebb2bed9a | 17 | bool _measurementAlreadyRead; |
amateusz | 0:d58ebb2bed9a | 18 | char count; |
amateusz | 2:e2db05bc4708 | 19 | float values[]; |
amateusz | 0:d58ebb2bed9a | 20 | }; |
amateusz | 0:d58ebb2bed9a | 21 | |
amateusz | 0:d58ebb2bed9a | 22 | Identification_struct _ident_struct; |
amateusz | 0:d58ebb2bed9a | 23 | |
amateusz | 0:d58ebb2bed9a | 24 | static int detect(SDI12 &sdi12, char indices[]) { |
amateusz | 0:d58ebb2bed9a | 25 | char found = 0; |
amateusz | 0:d58ebb2bed9a | 26 | for (char i = '1'; i < '9'; ++i) { |
amateusz | 0:d58ebb2bed9a | 27 | string question = "?!"; |
amateusz | 0:d58ebb2bed9a | 28 | question[0] = i; |
amateusz | 0:d58ebb2bed9a | 29 | sdi12.sendCommand(question); |
amateusz | 0:d58ebb2bed9a | 30 | std::string response; |
amateusz | 0:d58ebb2bed9a | 31 | |
amateusz | 0:d58ebb2bed9a | 32 | Timer detectTimer; |
amateusz | 0:d58ebb2bed9a | 33 | detectTimer.start(); |
amateusz | 0:d58ebb2bed9a | 34 | while (sdi12.RxBufferAvailable() == 0) |
amateusz | 0:d58ebb2bed9a | 35 | if(detectTimer.read_ms() > 800) { |
amateusz | 0:d58ebb2bed9a | 36 | ++i; |
amateusz | 0:d58ebb2bed9a | 37 | break; |
amateusz | 0:d58ebb2bed9a | 38 | } |
amateusz | 0:d58ebb2bed9a | 39 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 0:d58ebb2bed9a | 40 | char buffer[bufferSize]; |
amateusz | 0:d58ebb2bed9a | 41 | |
amateusz | 0:d58ebb2bed9a | 42 | sdi12.getRxBuffer(buffer); |
amateusz | 0:d58ebb2bed9a | 43 | // if first char is valid address char |
amateusz | 0:d58ebb2bed9a | 44 | if (buffer[0] >= '0' && buffer[0] <= '9' || |
amateusz | 0:d58ebb2bed9a | 45 | buffer[0] >= 'a' && buffer[0] <= 'z' || |
amateusz | 0:d58ebb2bed9a | 46 | buffer[0] >= 'A' && buffer[0] <= 'Z') { |
amateusz | 0:d58ebb2bed9a | 47 | indices[found++] = buffer[0]; |
amateusz | 0:d58ebb2bed9a | 48 | } |
amateusz | 0:d58ebb2bed9a | 49 | } |
amateusz | 0:d58ebb2bed9a | 50 | return found; |
amateusz | 0:d58ebb2bed9a | 51 | }; |
amateusz | 0:d58ebb2bed9a | 52 | |
amateusz | 2:e2db05bc4708 | 53 | SDI12_device (SDI12 &inst, char address, EventQueue &mainDispatcher) : _sdi12(inst) { |
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 | 0:d58ebb2bed9a | 58 | |
amateusz | 0:d58ebb2bed9a | 59 | // void printIdentification(){ |
amateusz | 0:d58ebb2bed9a | 60 | // Serial.println(_ident_struct.company); |
amateusz | 0:d58ebb2bed9a | 61 | // Serial.println(_ident_struct.model); |
amateusz | 0:d58ebb2bed9a | 62 | // Serial.println(_ident_struct.version); |
amateusz | 0:d58ebb2bed9a | 63 | // } |
amateusz | 0:d58ebb2bed9a | 64 | // |
amateusz | 2:e2db05bc4708 | 65 | |
amateusz | 0:d58ebb2bed9a | 66 | // // returns after how many seconds a measurement will be ready |
amateusz | 2:e2db05bc4708 | 67 | int measure(bool concurrent = true) { |
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 | 2:e2db05bc4708 | 76 | if(timeout.read_ms() > 100) { |
amateusz | 2:e2db05bc4708 | 77 | return false; |
amateusz | 2:e2db05bc4708 | 78 | } |
amateusz | 2:e2db05bc4708 | 79 | } |
amateusz | 2:e2db05bc4708 | 80 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 2:e2db05bc4708 | 81 | char buffer[bufferSize+1]; |
amateusz | 2:e2db05bc4708 | 82 | sdi12.getRxBuffer(buffer); |
amateusz | 2:e2db05bc4708 | 83 | buffer[bufferSize] = '\0'; |
amateusz | 2:e2db05bc4708 | 84 | std::string response(buffer); |
amateusz | 2:e2db05bc4708 | 85 | |
amateusz | 2:e2db05bc4708 | 86 | if (response[0] == _address) { |
amateusz | 2:e2db05bc4708 | 87 | char measurementsCount = std::atoi(response.substr(1+3,(concurrent?2:1)).c_str()); |
amateusz | 2:e2db05bc4708 | 88 | char waitFor = std::atoi(response.substr(1,3).c_str()); |
amateusz | 2:e2db05bc4708 | 89 | _measurement.count = measurementsCount; |
amateusz | 2:e2db05bc4708 | 90 | // _measurement.timestampMeasurementReadyAt |
amateusz | 2:e2db05bc4708 | 91 | debug("wait for %d measurement for %d seconds...", _measurement.count, waitFor); |
amateusz | 2:e2db05bc4708 | 92 | sensorQueue.call_in(waitFor * 1000, callback(this, &SDI12_device::read)); |
amateusz | 2:e2db05bc4708 | 93 | if (_measurement.values == NULL) delete[] _measurement.values; |
amateusz | 2:e2db05bc4708 | 94 | return 0; |
amateusz | 2:e2db05bc4708 | 95 | } |
amateusz | 2:e2db05bc4708 | 96 | return -1; |
amateusz | 2:e2db05bc4708 | 97 | }; |
amateusz | 0:d58ebb2bed9a | 98 | // |
amateusz | 0:d58ebb2bed9a | 99 | // bool isMeasurementReady(){ |
amateusz | 0:d58ebb2bed9a | 100 | // return (((unsigned)(_measurement.timestampMeasurementReadyAt - millis())>0)?false:true); |
amateusz | 0:d58ebb2bed9a | 101 | // }; |
amateusz | 0:d58ebb2bed9a | 102 | // |
amateusz | 0:d58ebb2bed9a | 103 | // short unsigned int measurementReadyIn(){ // ms |
amateusz | 0:d58ebb2bed9a | 104 | // if (isMeasurementReady()) |
amateusz | 0:d58ebb2bed9a | 105 | // return 0; |
amateusz | 0:d58ebb2bed9a | 106 | // else{ |
amateusz | 0:d58ebb2bed9a | 107 | // return _measurement.timestampMeasurementReadyAt - millis(); |
amateusz | 0:d58ebb2bed9a | 108 | // } |
amateusz | 0:d58ebb2bed9a | 109 | // }; |
amateusz | 0:d58ebb2bed9a | 110 | // |
amateusz | 2:e2db05bc4708 | 111 | bool read() { |
amateusz | 2:e2db05bc4708 | 112 | char alreadyRead = 0; |
amateusz | 2:e2db05bc4708 | 113 | |
amateusz | 2:e2db05bc4708 | 114 | std::string question = string("?") + string("D0") + string("!"); |
amateusz | 2:e2db05bc4708 | 115 | question[0] = _address; |
amateusz | 2:e2db05bc4708 | 116 | _sdi12.sendCommand(question); |
amateusz | 2:e2db05bc4708 | 117 | |
amateusz | 2:e2db05bc4708 | 118 | Timer timeout; |
amateusz | 2:e2db05bc4708 | 119 | timeout.start(); |
amateusz | 2:e2db05bc4708 | 120 | while (sdi12.RxBufferAvailable() == 0) { |
amateusz | 2:e2db05bc4708 | 121 | if (sdi12.RxInProgress()) timeout.reset(); |
amateusz | 2:e2db05bc4708 | 122 | if(timeout.read_ms() > 100) { |
amateusz | 2:e2db05bc4708 | 123 | return false; |
amateusz | 2:e2db05bc4708 | 124 | } |
amateusz | 2:e2db05bc4708 | 125 | } |
amateusz | 2:e2db05bc4708 | 126 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 2:e2db05bc4708 | 127 | char buffer[bufferSize+1]; |
amateusz | 2:e2db05bc4708 | 128 | sdi12.getRxBuffer(buffer); |
amateusz | 2:e2db05bc4708 | 129 | buffer[bufferSize] = '\0'; |
amateusz | 2:e2db05bc4708 | 130 | std::string response(buffer); |
amateusz | 2:e2db05bc4708 | 131 | |
amateusz | 2:e2db05bc4708 | 132 | debug("parser"); |
amateusz | 2:e2db05bc4708 | 133 | // if (response[0] == _address) { |
amateusz | 2:e2db05bc4708 | 134 | // debug("parser"); |
amateusz | 2:e2db05bc4708 | 135 | // // parser here |
amateusz | 2:e2db05bc4708 | 136 | // response = response.substr(1); // to limit repeting this operation later |
amateusz | 2:e2db05bc4708 | 137 | // // the only two possible delimeters of a value |
amateusz | 2:e2db05bc4708 | 138 | // uint8_t start_index = 0; |
amateusz | 0:d58ebb2bed9a | 139 | // |
amateusz | 2:e2db05bc4708 | 140 | // int8_t index_pos = response.indexOf('+', start_index); |
amateusz | 2:e2db05bc4708 | 141 | // int8_t index_neg = response.indexOf('-', start_index); |
amateusz | 0:d58ebb2bed9a | 142 | // |
amateusz | 2:e2db05bc4708 | 143 | // Serial.println(index_pos); |
amateusz | 2:e2db05bc4708 | 144 | // Serial.println(index_pos); |
amateusz | 0:d58ebb2bed9a | 145 | // |
amateusz | 2:e2db05bc4708 | 146 | // do { |
amateusz | 2:e2db05bc4708 | 147 | // // determine start index: |
amateusz | 2:e2db05bc4708 | 148 | // if (index_pos != -1 && index_neg != -1) start_index = min(index_pos,index_neg); |
amateusz | 2:e2db05bc4708 | 149 | // else if (index_pos == -1) start_index = index_neg; |
amateusz | 2:e2db05bc4708 | 150 | // else if (index_neg == -1) start_index = index_pos; |
amateusz | 0:d58ebb2bed9a | 151 | // |
amateusz | 2:e2db05bc4708 | 152 | // int8_t index_pos_next = response.indexOf('+', start_index +1); |
amateusz | 2:e2db05bc4708 | 153 | // int8_t index_neg_next = response.indexOf('-', start_index +1); |
amateusz | 0:d58ebb2bed9a | 154 | // |
amateusz | 2:e2db05bc4708 | 155 | // uint8_t end_index; |
amateusz | 2:e2db05bc4708 | 156 | // if (index_pos_next != -1 && index_neg_next != -1) end_index = min(index_pos_next,index_neg_next); |
amateusz | 2:e2db05bc4708 | 157 | // else if (index_pos_next == -1) end_index = index_neg_next; |
amateusz | 2:e2db05bc4708 | 158 | // else if (index_neg_next == -1) end_index = index_pos_next; |
amateusz | 0:d58ebb2bed9a | 159 | // |
amateusz | 2:e2db05bc4708 | 160 | // _measurement.values[alreadyRead++] = response.substr(start_index, end_index).toFloat(); |
amateusz | 2:e2db05bc4708 | 161 | // |
amateusz | 2:e2db05bc4708 | 162 | // index_pos = response.indexOf('+', start_index); |
amateusz | 2:e2db05bc4708 | 163 | // index_neg = response.indexOf('-', start_index); |
amateusz | 2:e2db05bc4708 | 164 | // } while(index_pos != -1 || index_neg != -1); |
amateusz | 0:d58ebb2bed9a | 165 | // } |
amateusz | 2:e2db05bc4708 | 166 | } |
amateusz | 0:d58ebb2bed9a | 167 | // |
amateusz | 2:e2db05bc4708 | 168 | unsigned char getMeasurementCount() { |
amateusz | 2:e2db05bc4708 | 169 | return _measurement.count; |
amateusz | 2:e2db05bc4708 | 170 | } |
amateusz | 2:e2db05bc4708 | 171 | |
amateusz | 2:e2db05bc4708 | 172 | float getMeasurementValue(char which) { |
amateusz | 2:e2db05bc4708 | 173 | return _measurement.values[which]; |
amateusz | 2:e2db05bc4708 | 174 | } |
amateusz | 2:e2db05bc4708 | 175 | |
amateusz | 0:d58ebb2bed9a | 176 | void setAddress(char address) { |
amateusz | 0:d58ebb2bed9a | 177 | _address = address; |
amateusz | 0:d58ebb2bed9a | 178 | }; |
amateusz | 0:d58ebb2bed9a | 179 | // |
amateusz | 0:d58ebb2bed9a | 180 | // |
amateusz | 0:d58ebb2bed9a | 181 | private: |
amateusz | 0:d58ebb2bed9a | 182 | SDI12 &_sdi12; |
amateusz | 0:d58ebb2bed9a | 183 | char _address; |
amateusz | 0:d58ebb2bed9a | 184 | Measurement_struct _measurement; |
amateusz | 0:d58ebb2bed9a | 185 | |
amateusz | 2:e2db05bc4708 | 186 | EventQueue sensorQueue; |
amateusz | 2:e2db05bc4708 | 187 | |
amateusz | 1:6b1a21925a81 | 188 | bool getIdentification(Identification_struct &ident) { |
amateusz | 1:6b1a21925a81 | 189 | // _sdi12.sendCommand(std::string(_address) + "I!"); |
amateusz | 1:6b1a21925a81 | 190 | std::string question = "?I!"; |
amateusz | 1:6b1a21925a81 | 191 | question[0] = _address; |
amateusz | 1:6b1a21925a81 | 192 | _sdi12.sendCommand(question); |
amateusz | 0:d58ebb2bed9a | 193 | |
amateusz | 1:6b1a21925a81 | 194 | Timer timeout; |
amateusz | 1:6b1a21925a81 | 195 | timeout.start(); |
amateusz | 1:6b1a21925a81 | 196 | while (sdi12.RxBufferAvailable() == 0) { |
amateusz | 1:6b1a21925a81 | 197 | if (sdi12.RxInProgress()) timeout.reset(); |
amateusz | 1:6b1a21925a81 | 198 | if(timeout.read_ms() > 20) { |
amateusz | 1:6b1a21925a81 | 199 | return false; |
amateusz | 1:6b1a21925a81 | 200 | } |
amateusz | 1:6b1a21925a81 | 201 | } |
amateusz | 1:6b1a21925a81 | 202 | unsigned char bufferSize = sdi12.RxBufferAvailable(); |
amateusz | 1:6b1a21925a81 | 203 | char buffer[bufferSize+1]; |
amateusz | 1:6b1a21925a81 | 204 | sdi12.getRxBuffer(buffer); |
amateusz | 1:6b1a21925a81 | 205 | buffer[bufferSize] = '\0'; |
amateusz | 1:6b1a21925a81 | 206 | std::string response(buffer); |
amateusz | 0:d58ebb2bed9a | 207 | |
amateusz | 1:6b1a21925a81 | 208 | if (response[0] == _address) { |
amateusz | 1:6b1a21925a81 | 209 | // e.g.: 113DECAGON GS3 402 |
amateusz | 2:e2db05bc4708 | 210 | |
amateusz | 1:6b1a21925a81 | 211 | ident.sdi_version = std::atoi(response.substr(1, 2).c_str()); |
amateusz | 2:e2db05bc4708 | 212 | debug("|%d| /%s/\r\n",ident.sdi_version ,response.substr(1, 2).c_str()); |
amateusz | 1:6b1a21925a81 | 213 | |
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 | 0:d58ebb2bed9a | 227 | }; |