muwerk mupplet Sensor Library
muwerk applets; mupplets: functional units that support specific hardware or reusable applications for sensors
Loading...
Searching...
No Matches
mup_gamma_gdk101.h
1// http://allsmartlab.com/eng/294-2/
2// http://allsmartlab.com/wp-content/uploads/2017/download/GDK101datasheet_v1.5.pdf
3// http://allsmartlab.com/wp-content/uploads/2017/download/GDK101_Application_Note.zip
4
5// mup_gamma_gdk101.h
6#pragma once
7
8#ifndef tiny_twi_h
9#include <Wire.h>
10#else
11typedef TinyWire TwoWire;
12#endif
13
14#include "helper/mup_i2c_registers.h"
15
16#include "scheduler.h"
17#include "sensors.h"
18
19namespace ustd {
20
21// clang-format off
98// clang-format on
100 private:
101 String GDK101_VERSION = "0.1.0";
102 Scheduler *pSched;
103 TwoWire *pWire;
104 I2CRegisters *pI2C;
105 int tID;
106 String name;
107 double gamma10minavgValue, gamma1minavgValue;
108
109 public:
110 enum GDKSensorState { UNAVAILABLE,
111 IDLE,
112 MEASUREMENT_WAIT,
113 WAIT_NEXT_MEASUREMENT };
114
122 };
123 GDKSensorState sensorState;
124 bool disIrq = false;
125 unsigned long errs = 0;
126 unsigned long oks = 0;
127 unsigned long basePollRateUs = 50000; // 50uS
128 unsigned long pollRateMs = 2000; // 2s
129 uint32_t lastPollMs = 0;
130 time_t watchdogTime = 0;
131 bool watchdogActive = true;
132 uint32_t watchdogTimeoutSec = 900;
133 uint32_t watchdogStartupTimeoutSec = 180;
134
135 enum FilterMode { FAST,
136 MEDIUM,
137 LONGTERM };
138 String firmwareVersion;
139 FilterMode filterMode;
140 uint8_t i2cAddress;
141 ustd::sensorprocessor gamma10minavgSensor = ustd::sensorprocessor(4, 600, 0.005);
142 ustd::sensorprocessor gamma1minavgSensor = ustd::sensorprocessor(4, 600, 0.005);
143 bool bActive = false;
144
145 GammaGDK101(String name, FilterMode filterMode = FilterMode::FAST, uint8_t i2cAddress = 0x18)
146 : name(name), filterMode(filterMode), i2cAddress(i2cAddress) {
152 sensorState = GDKSensorState::UNAVAILABLE;
153 pI2C = nullptr;
154 setFilterMode(filterMode, true);
155 }
156
157 ~GammaGDK101() {
158 if (pI2C) {
159 delete pI2C;
160 }
161 }
162
167 return gamma10minavgValue;
168 }
169
174 return gamma1minavgValue;
175 }
176
177 void begin(Scheduler *_pSched, TwoWire *_pWire = &Wire, uint32_t _pollRateMs = 2000L, bool forceSlowClock = false, bool watchdog = true) {
178 pSched = _pSched;
179 pWire = _pWire;
180 pollRateMs = _pollRateMs;
181 watchdogActive = watchdog;
182
183 if (watchdogActive) {
184 resetWatchdog();
185 }
186
187 pWire->begin(); // required!
188 if (forceSlowClock) {
189 pWire->setClock(100000L);
190 disIrq = true;
191 }
192 pI2C = new I2CRegisters(pWire, i2cAddress);
193 auto ft = [=]() { this->loop(); };
194 tID = pSched->add(ft, name, basePollRateUs);
195
196 auto fnall = [=](String topic, String msg, String originator) {
197 this->subsMsg(topic, msg, originator);
198 };
199 pSched->subscribe(tID, name + "/sensor/#", fnall);
200
201 // I2c_checkAddress kills the sensor!
202 // lastError=i2c_checkAddress(i2cAddress);
203
204 bActive = resetGDKSensor();
205 if (bActive) {
206 firmwareVersion = getGDKFirmwareVersion();
207 }
208 }
209
210 void setFilterMode(FilterMode mode, bool silent = false) {
211 switch (mode) {
212 case FAST:
213 filterMode = FAST;
214 gamma10minavgSensor.update(1, 2, 0.05);
215 gamma1minavgSensor.update(1, 2, 0.1);
216 break;
217 case MEDIUM:
218 filterMode = MEDIUM;
219 gamma10minavgSensor.update(4, 30, 0.1);
220 gamma1minavgSensor.update(4, 30, 0.5);
221 break;
222 case LONGTERM:
223 default:
224 filterMode = LONGTERM;
225 gamma10minavgSensor.update(10, 600, 0.1);
226 gamma1minavgSensor.update(10, 600, 0.5);
227 break;
228 }
229 if (!silent)
230 publishFilterMode();
231 }
232
233 private:
234 void publishGamma10minavg() {
235 char buf[32];
236 sprintf(buf, "%6.3f", gamma10minavgValue);
237 pSched->publish(name + "/sensor/gamma10minavg", buf);
238 }
239
240 void publishGamma1minavg() {
241 char buf[32];
242 sprintf(buf, "%6.3f", gamma1minavgValue);
243 pSched->publish(name + "/sensor/gamma1minavg", buf);
244 }
245
246 void publishError(String errMsg) {
247 pSched->publish(name + "/sensor/error", errMsg);
248 }
249
250 void publishFirmwareVersion() {
251 pSched->publish(name + "/sensor/firmwareVersion", firmwareVersion);
252 }
253
254 void publishFilterMode() {
255 switch (filterMode) {
256 case FilterMode::FAST:
257 pSched->publish(name + "/sensor/mode", "FAST");
258 break;
259 case FilterMode::MEDIUM:
260 pSched->publish(name + "/sensor/mode", "MEDIUM");
261 break;
262 case FilterMode::LONGTERM:
263 pSched->publish(name + "/sensor/mode", "LONGTERM");
264 break;
265 }
266 }
267
268 String getGDKFirmwareVersion() {
269 uint16_t data;
270 if (!pI2C->readRegisterWord(0xb4, &data, true, disIrq)) { // version
271#ifdef USE_SERIAL_DBG
272 Serial.print("Failed to read version GDK101 at address 0x");
273 Serial.print(i2cAddress, HEX);
274 Serial.print(" data: ");
275 Serial.print(data, HEX);
276 Serial.print(" lasterr: ");
277 Serial.println(pI2C->lastError, HEX);
278 return "unknown";
279#endif
280 } else {
281 uint8_t h = data >> 8;
282 uint8_t l = data & 0xff;
283 char buf[64];
284 sprintf(buf, "V%d.%d", h, l);
285 Serial.print("Firmware version GTK ");
286 Serial.println(buf);
287 return String(buf);
288 }
289 }
290
291 bool resetGDKSensor() {
292 uint16_t data;
293 if (!pI2C->readRegisterWord(0xa0, &data, true, disIrq)) { // reset
294#ifdef USE_SERIAL_DBG
295 Serial.print("Failed to reset GDK101 at address 0x");
296 Serial.print(i2cAddress, HEX);
297 Serial.print(" data: ");
298 Serial.print(data, HEX);
299 Serial.print(" lasterr: ");
300 Serial.println(pI2C->lastError, HEX);
301#endif
302 pSched->publish("dbg/1", "RESFAIL");
303 bActive = false;
304 return false;
305 } else {
306 if ((data >> 8) == 1) {
307 bActive = true;
308#ifdef USE_SERIAL_DBG
309 Serial.print("GDK101 sensor found at address 0x");
310 Serial.print(i2cAddress, HEX);
311 Serial.print(". Reset returned: ");
312 Serial.println(data, HEX);
313#endif
314 } else {
315 Serial.print("Failed to reset GDK101 at address 0x");
316 Serial.print(i2cAddress, HEX);
317 Serial.print(" data: ");
318 Serial.print(data, HEX);
319 Serial.print(" lasterr: ");
320 Serial.println(pI2C->lastError, HEX);
321 }
322 }
323 resetWatchdog();
324 return bActive;
325 }
326
327 bool readGDKSensorMeasurement(uint8_t reg, double *pMeas) {
328 uint16_t data;
329 *pMeas = 0.0;
330 if (!pI2C->readRegisterWord(reg, &data, true, disIrq)) {
331#ifdef USE_SERIAL_DBG
332 Serial.print("Failed to read GDK101 at address 0x");
333 Serial.print(i2cAddress, HEX);
334 Serial.print(" data: ");
335 Serial.print(data, HEX);
336 Serial.print(" lasterr: ");
337 Serial.println(pI2C->lastError, HEX);
338#endif
339 return false;
340 } else {
341 double ms = (double)(data >> 8) + (double)(data & 0xff) / 100.0;
342 *pMeas = ms;
343#ifdef USE_SERIAL_DBG
344 Serial.println("GDK101 Measurement: " + String(ms));
345#endif
346 return true;
347 }
348 }
349
350 bool readGDKSensor(double *pGamma10minavgVal, double *pGamma1minavgVal) {
351 *pGamma10minavgVal = 0.0;
352 *pGamma1minavgVal = 0.0;
353 if (!readGDKSensorMeasurement(0xb2, pGamma10minavgVal)) return false;
354 if (!readGDKSensorMeasurement(0xb3, pGamma1minavgVal)) return false;
355 return true;
356 }
357
358 void resetWatchdog() {
359 watchdogTime = time(nullptr);
360 }
361
362 void loop() {
363 if (timeDiff(lastPollMs, millis()) > pollRateMs) {
364 lastPollMs = millis();
365 double gamma10minavgVal, gamma1minavgVal;
366 if (bActive) {
367 if (readGDKSensor(&gamma10minavgVal, &gamma1minavgVal)) {
368 if (gamma10minavgVal != 0 || gamma1minavgVal != 0) {
369 resetWatchdog(); // Valid measurement received, restart watchdog.
370 }
371 if (watchdogActive) {
372 if (timeDiff(watchdogTime, time(nullptr)) > watchdogTimeoutSec) {
373 publishError("Watchdog timeout, resetting sensor");
374 resetWatchdog();
375 resetGDKSensor();
376 }
377 }
378 if (gamma10minavgSensor.filter(&gamma10minavgVal)) {
379 gamma10minavgValue = gamma10minavgVal;
380 publishGamma10minavg();
381 }
382 if (gamma1minavgSensor.filter(&gamma1minavgVal)) {
383 gamma1minavgValue = gamma1minavgVal;
384 publishGamma1minavg();
385 }
386 }
387 } else {
388 if (watchdogActive) {
389 if (timeDiff(watchdogTime, time(nullptr)) > watchdogStartupTimeoutSec) {
390 publishError("Watchdog timeout during startup, resetting sensor");
391 resetWatchdog();
392 bActive = resetGDKSensor();
393 }
394 }
395 }
396 }
397 }
398
399 void subsMsg(String topic, String msg, String originator) {
400 if (topic == name + "/sensor/gamma10minavg/get") {
401 publishGamma10minavg();
402 } else if (topic == name + "/sensor/gamma1minavg/get") {
403 publishGamma1minavg();
404 } else if (topic == name + "/sensor/mode/get") {
405 publishFilterMode();
406 } else if (topic == name + "/sensor/mode/set") {
407 if (msg == "fast" || msg == "FAST") {
408 setFilterMode(FilterMode::FAST);
409 } else {
410 if (msg == "medium" || msg == "MEDIUM") {
411 setFilterMode(FilterMode::MEDIUM);
412 } else {
413 setFilterMode(FilterMode::LONGTERM);
414 }
415 }
416 } else if (topic == name + "/sensor/firmwareversion/get") {
417 publishFirmwareVersion();
418 }
419 }
420
421}; // GammaGDK
422
423} // namespace ustd
mupplet-sensor temperature and pressure with GDK101
Definition: mup_gamma_gdk101.h:99
GDKSampleMode
Definition: mup_gamma_gdk101.h:116
@ STANDARD
4 samples, pressure resolution 18bit / 0.66 Pa, rec temperature oversampling: x1
Definition: mup_gamma_gdk101.h:119
@ ULTRA_LOW_POWER
1 samples, pressure resolution 16bit / 2.62 Pa, rec temperature oversampling: x1
Definition: mup_gamma_gdk101.h:117
@ HIGH_RESOLUTION
8 samples, pressure resolution 19bit / 0.33 Pa, rec temperature oversampling: x1
Definition: mup_gamma_gdk101.h:120
@ ULTRA_HIGH_RESOLUTION
16 samples, pressure resolution 20bit / 0.16 Pa, rec temperature oversampling: x2
Definition: mup_gamma_gdk101.h:121
@ LOW_POWER
2 samples, pressure resolution 17bit / 1.31 Pa, rec temperature oversampling: x1
Definition: mup_gamma_gdk101.h:118
double getGamma1minavt()
Definition: mup_gamma_gdk101.h:170
GammaGDK101(String name, FilterMode filterMode=FilterMode::FAST, uint8_t i2cAddress=0x18)
Definition: mup_gamma_gdk101.h:145
double getGamma10minavt()
Definition: mup_gamma_gdk101.h:163