/* xsns_78_ezo.ino - EZO modules base class Copyright (C) 2020 Christopher Tremblay This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef USE_I2C #if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) #define D_EZO_DELAY 300 // Minimum delay for any instruction #define D_EZO_MAX_BUF 40 // Maximum response const char D_EZO_NAME[] PROGMEM = "EZO"; // This baseclass provides common functionality for all EZO devices struct EZOStruct { EZOStruct(uint32_t addr) : valid(0), addr(addr), lastRead(-2000) {} void MeasureRequest(void) { const uint8_t EZOMeasureCmd[2] = {'R', 0}; if (valid) { valid--; } Wire.beginTransmission(addr); Wire.write(EZOMeasureCmd, sizeof(EZOMeasureCmd)); Wire.endTransmission(); lastRead = millis(); } void HandleCommand(char *cmd, uint32_t len) const { // Transmit our command verbatim Wire.beginTransmission(addr); Wire.write(cmd, len); if (Wire.endTransmission() != 0) { return; } // Attempt to read the results char data[D_EZO_MAX_BUF]; for (uint32_t code = 254; code == 254; code = Wire.read()) { delay(D_EZO_DELAY); Wire.requestFrom(addr, sizeof(data)); } for (uint32_t i = 0; Wire.available() > 0; i++) { data[i] = Wire.read(); } ResponseCmndChar((char *)data); } bool isValid(void) { return valid; } virtual void ProcessMeasurement(void); virtual void Show(bool json, const char *name); protected: void ProcessMeasurement(char *const data, const uint32_t len, const uint32_t latency) { // Wait for the data to arrive first const int32_t dur = lastRead + latency - millis(); // Wait for the last readout to complete (only when commands are issued) if (dur > 0) { delay(dur); } Wire.requestFrom(addr, len); const char code = Wire.read(); if (code == 1) { for (uint32_t i = 0; (Wire.available() > 0) && (i < len); i++) { data[i] = Wire.read(); } valid = SENSOR_MAX_MISS; } } uint8_t valid; uint8_t addr; uint32_t lastRead; }; #endif // USE_EZO* #endif // USE_I2C