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
00001 #include "SDI12.h" 00002 #include <string> 00003 #include "mbed.h" 00004 extern void printStackStats(char num); 00005 00006 class SDI12_device 00007 { 00008 public: 00009 struct Identification_struct { 00010 unsigned char sdi_version; 00011 char company[8+1]; 00012 char model[6+1]; 00013 char version[3+1]; 00014 }; 00015 00016 Identification_struct _ident_struct; 00017 00018 struct Measurement_struct { 00019 unsigned long timestampMeasurementReadyAt; 00020 char readyIn; 00021 bool _measurementAlreadyRead; 00022 char count; 00023 // float * values; // not float values [] !! :O 00024 float values[20]; // !! :O 00025 }; 00026 00027 const static int detect(SDI12 &sdi12, char indices[], int stop = -1, int start = -1) { 00028 char found = 0; 00029 for (size_t i = (start==-1?0:start); i < (stop==-1?ADDRRICES.size():stop+1); ++i) { 00030 const std::string question = std::string(1, ADDRRICES[i]) + "!"; 00031 sdi12.sendCommand(question); 00032 Timer detectTimer; 00033 detectTimer.start(); 00034 while (detectTimer.read_ms() < RESPONSE_TIMEOUT * 4) { 00035 if (sdi12.RxInProgress()) detectTimer.reset(); 00036 if (sdi12.RxBufferAvailable()) { 00037 unsigned char bufferSize = sdi12.RxBufferAvailable(); 00038 char buffer[bufferSize]; 00039 sdi12.getRxBuffer(buffer); 00040 // if first char is valid address char 00041 if (ADDRRICES.find(buffer[0])) { 00042 indices[found++] = buffer[0]; 00043 debug("FOUND (%d): %d -> %c\r\n", found, i, indices[found-1]); 00044 } 00045 } 00046 } 00047 osDelay(100); 00048 } 00049 return found; 00050 }; 00051 00052 SDI12_device() { 00053 debug("default in %s\r\n", __FILE__); 00054 } 00055 00056 SDI12_device (SDI12 *inst, char address) : _sdi12(inst) { 00057 setAddress(address); 00058 if(getIdentification(_ident_struct)); 00059 }; 00060 00061 SDI12_device (const SDI12_device &old) { 00062 debug("copy in %s\r\n", __FILE__); 00063 _address = old._address; 00064 _ident_struct = old._ident_struct; 00065 _sdi12 = old._sdi12; 00066 _measurement = old._measurement; 00067 _measurementReady = false; 00068 _valuesReadyCount = old._valuesReadyCount; 00069 _measurementReady = old._measurementReady; // why?!?!! new _measureStruct here worked ?! 00070 } 00071 00072 SDI12_device & operator= (const SDI12_device & old) { 00073 debug("assign in %s\r\n", __FILE__); 00074 _address = old._address; 00075 _ident_struct = old._ident_struct; 00076 _sdi12 = old._sdi12; 00077 _measurement = old._measurement; 00078 _measurementReady = false; 00079 _valuesReadyCount = old._valuesReadyCount; 00080 _measurementReady = old._measurementReady; // why?!?!! new _measureStruct here worked ?! 00081 00082 return *this; 00083 } 00084 00085 ~SDI12_device () { 00086 debug("destructor in %s\r\n", __FILE__); 00087 } 00088 00089 bool present() { 00090 const std::string question = std::string(1, _address) + std::string("!"); 00091 _sdi12->sendCommand(question); 00092 00093 Timer timeout; 00094 timeout.start(); 00095 while (sdi12.RxBufferAvailable() == 0) { 00096 if (sdi12.RxInProgress()) timeout.reset(); 00097 if(timeout.read_ms() > RESPONSE_TIMEOUT) { 00098 return false; 00099 } 00100 } 00101 unsigned char bufferSize = sdi12.RxBufferAvailable(); 00102 char buffer[bufferSize]; 00103 sdi12.getRxBuffer(buffer); // only to flush the buffer 00104 return true; 00105 } 00106 // concurrent means that device under measurement won't signal its prempt readiness to the bus 00107 int measure(bool concurrent = true, char group = '0') { 00108 00109 const std::string question = std::string(1, _address) + std::string(concurrent?"C": (group=='0'?"M":("M"+std::string(1,group)))) + std::string("!"); 00110 // if (group != '0') // ABOVE DOES THIS 00111 // question.insert(2, 1, group); // e.g. 2M! -> 2M1! 00112 _sdi12->sendCommand(question); 00113 00114 Timer timeout; 00115 timeout.start(); 00116 while (sdi12.RxBufferAvailable() == 0) { 00117 if (sdi12.RxInProgress()) timeout.reset(); 00118 if(timeout.read_ms() > RESPONSE_TIMEOUT) { 00119 return -2; 00120 } 00121 } 00122 00123 unsigned char bufferSize = sdi12.RxBufferAvailable(); 00124 char buffer[bufferSize+1]; 00125 sdi12.getRxBuffer(buffer); 00126 buffer[bufferSize] = '\0'; 00127 std::string response(buffer); 00128 00129 if (response[0] == _address) { 00130 char measurementsCount = std::atoi(response.substr(1+3,(concurrent?2:1)).c_str()); 00131 char waitFor = std::atoi(response.substr(1,3).c_str()); 00132 _measurement.count = measurementsCount; 00133 00134 _measurement.readyIn = waitFor; 00135 // _measurement.timestampMeasurementReadyAt 00136 debug("wait for %d measurement for %d seconds...", _measurement.count, waitFor); 00137 _valuesReadyCount = 0; 00138 _measurementReady = false; 00139 return 0; 00140 } 00141 return -1; 00142 }; 00143 00144 char readyIn() { 00145 return _measurement.readyIn; 00146 } 00147 00148 bool isReady() { 00149 return _measurementReady; 00150 } 00151 00152 bool read(char group = '0') { 00153 char group_a[] = {group}; 00154 printStackStats(std::atoi(group_a)); 00155 // Measurement (M), Continuous (R), and Concurrent (C) commands and subsequent Data (D) 00156 const std::string question = std::string(1, _address) + std::string("D") + std::string(1, group)+ std::string("!"); 00157 _sdi12->sendCommand(question); 00158 00159 Timer timeout; 00160 timeout.start(); 00161 while (sdi12.RxBufferAvailable() == 0) { 00162 if (sdi12.RxInProgress()) timeout.reset(); 00163 if(timeout.read_ms() > RESPONSE_TIMEOUT) { 00164 return false; 00165 } 00166 } 00167 unsigned char bufferSize = sdi12.RxBufferAvailable(); 00168 char buffer[bufferSize+1]; 00169 sdi12.getRxBuffer(buffer); 00170 buffer[bufferSize] = '\0'; 00171 const std::string response(buffer); 00172 00173 // debug("parser recv: %s\r\n", response); 00174 if (response[0] == _address && response.size() > 1) { 00175 // debug("__%s__\r\n", response); 00176 // parser here 00177 // const!!! response = response.substr(1); // to limit repeting this operation later. i.e. extract only values e.g. +21.3-123+123 00178 // the only two possible delimeters of a value 00179 size_t next_start_index = response.find_first_of("-+", 0 + 1); // address offset! 00180 size_t next_end_index; 00181 // ready, steady, parse!! 00182 while(next_start_index != std::string::npos) { 00183 // determine start index: 00184 next_end_index = response.find_first_of("-+", next_start_index + 1); // std::substr is prepared to take std::npos 00185 00186 float value = std::atof(response.substr(next_start_index, next_end_index).c_str()); 00187 // debug("parsed: %f\r\n", value); 00188 _measurement.values[_valuesReadyCount++] = value; 00189 next_start_index = response.find_first_of("-+", next_end_index); 00190 } 00191 // if current parsing doesn't return all the expexted measurements, then press harder and poll further Dx commands. RECURSION HERE *.* 00192 if (_valuesReadyCount < _measurement.count) { 00193 debug("values count: %d\r\n", _valuesReadyCount); 00194 read(group + 1); 00195 } else { 00196 _measurementReady = true; 00197 } 00198 } 00199 return true; 00200 } 00201 00202 00203 // 00204 const unsigned char getMeasurementCount() { 00205 return _measurement.count; 00206 } 00207 00208 const float getMeasurementValue(char which) { 00209 _measurementReady = false; // reading /any/ of the values resets this 00210 return _measurement.values[which]; 00211 } 00212 00213 void setAddress(char address) { 00214 _address = address; 00215 }; 00216 // 00217 // 00218 private: 00219 static const int RESPONSE_TIMEOUT = 15+1; // device should start to respond within [ms] 00220 static const std::string ADDRRICES; // as in index -> indices, 00221 00222 SDI12 *_sdi12; 00223 char _address; 00224 00225 Measurement_struct _measurement; 00226 size_t _valuesReadyCount; 00227 bool _measurementReady; 00228 00229 bool getIdentification(Identification_struct &ident) { 00230 // _sdi12->sendCommand(std::string(_address) + "I!"); 00231 const std::string question = std::string(1, _address) + "I!"; 00232 _sdi12->sendCommand(question); 00233 00234 Timer timeout; 00235 timeout.start(); 00236 while (sdi12.RxBufferAvailable() == 0) { 00237 if (sdi12.RxInProgress()) timeout.reset(); 00238 if(timeout.read_ms() > RESPONSE_TIMEOUT) { 00239 return false; 00240 } 00241 } 00242 unsigned char bufferSize = sdi12.RxBufferAvailable(); 00243 char buffer[bufferSize+1]; 00244 sdi12.getRxBuffer(buffer); 00245 buffer[bufferSize] = '\0'; 00246 const std::string response(buffer); 00247 00248 if (response[0] == _address) { 00249 // e.g.: 113DECAGON GS3 402 00250 00251 ident.sdi_version = std::atoi(response.substr(1, 2).c_str()); 00252 const std::string tempStr = response.substr(3, 8); 00253 strcpy(ident.company, tempStr.c_str()); 00254 00255 strcpy(ident.model, response.substr(3+8, 6).c_str()); 00256 00257 strcpy(ident.version, response.substr(3+8+6, 3).c_str()); 00258 return true; 00259 } 00260 return false; 00261 } 00262 }; 00263 00264 const std::string SDI12_device::ADDRRICES = "0123456789abcdefgijklmnoprstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ";
Generated on Sat Jul 30 2022 04:05:09 by
1.7.2