Represents a single device. Take measurements, send commands. Needs SDI12 bus instance as argument. Allows to detect devices on the bus

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?

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 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 };