diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 2347cba22..a4de6d1bd 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -106,8 +106,10 @@ #define D_JSON_PRESSURE "Pressure" #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PRESSURE_UNIT "PressureUnit" +#define D_JSON_PROBETEMPERATURE "ProbeTemperature" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" +#define D_JSON_REFERENCETEMPERATURE "ReferenceTemperature" #define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 2ea9c249a..20b4f8ddb 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8684ac7a0..69f21dec7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -285,6 +285,9 @@ // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// -- SPI sensors ---------------------------------- +#define USE_MAX31855 // Enable MAX31855 K-Type thermocouple sensor + // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 48af9cf4b..d8a9296e7 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -143,6 +143,9 @@ enum UserSelectablePins { GPIO_RF_SENSOR, // Rf receiver with sensor decoding GPIO_AZ_TXD, // AZ-Instrument 7798 Serial interface GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface + GPIO_MAX31855CS, // MAX31855 Serial interface + GPIO_MAX31855CLK, // MAX31855 Serial interface + GPIO_MAX31855DO, // MAX31855 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -204,7 +207,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" D_SENSOR_RF_SENSOR "|" - D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX; + D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" + D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO; /********************************************************************************************/ @@ -461,6 +465,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface GPIO_AZ_RXD // AZ-Instrument 7798 CO2 datalogger Serial interface #endif +#ifdef USE_MAX31855 + GPIO_MAX31855CS, // MAX31855 Serial interface + GPIO_MAX31855CLK, // MAX31855 Serial interface + GPIO_MAX31855DO, // MAX31855 Serial interface +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino new file mode 100644 index 000000000..2668f914c --- /dev/null +++ b/sonoff/xsns_39_max31855.ino @@ -0,0 +1,163 @@ +/* + xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Markus Past + + 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 . +*/ + +//#define USE_MAX31855 + +#ifdef USE_MAX31855 + +#define XSNS_39 39 + +bool initialized = false; + +struct MAX31855_ResultStruct{ + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void){ + if(initialized) + return; + + pinMode(pin[GPIO_MAX31855CS], OUTPUT); + pinMode(pin[GPIO_MAX31855CLK], OUTPUT); + pinMode(pin[GPIO_MAX31855DO], INPUT); + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + + initialized = true; +} + +void MAX31855_GetResult(void){ + int32_t RawData = MAX31855_ShiftIn(32); + uint8_t probeerror = RawData & 0x7; + + MAX31855_Result.ErrorCode = probeerror; + MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; + else + MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); +} + +float MAX31855_GetProbeTemperature(int32_t RawData){ + if(RawData & 0x80000000) + RawData = (RawData >> 18) | 0xFFFFC000; + else + RawData >>= 18; + + float result = (RawData * 0.25); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + +float MAX31855_GetReferenceTemperature(int32_t RawData){ + if(RawData & 0x8000) + RawData = (RawData >> 4) | 0xFFFFF000; + else + RawData = (RawData >> 4) & 0x00000FFF; + + float result = (RawData * 0.0625); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + +int32_t MAX31855_ShiftIn(uint8_t Length){ + int32_t dataIn = 0; + + digitalWrite(pin[GPIO_MAX31855CS], LOW); + delayMicroseconds(1); + + for(uint8_t i = 0; i < Length; i++) + { + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + delayMicroseconds(1); + dataIn <<= 1; + if(digitalRead(pin[GPIO_MAX31855DO])) + dataIn |= 1; + digitalWrite(pin[GPIO_MAX31855CLK], HIGH); + delayMicroseconds(1); + } + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + return dataIn; +} + +void MAX31855_Show(bool Json){ + char probetemp[33]; + char referencetemp[33]; + dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); + dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + + if(Json){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + mqtt_data, "MAX31855", probetemp, referencetemp, MAX31855_Result.ErrorCode); + } else { +#ifdef USE_WEBSERVER + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "MAX31855", probetemp, TempUnit()); +#endif // USE_WEBSERVER + } +} + + +// void MAX31855_ShowDebug(void){ +// char probetemp[33]; +// char referencetemp[33]; +// dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); +// dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + +// snprintf_P(mqtt_data, sizeof(mqtt_data), "%s %d %s %d %s %d %s %d %s %d %s %s %s %s %s %d", \ +// "CS:", pin[GPIO_MAX31855CS], "CLK:", pin[GPIO_MAX31855CLK], "DO:", pin[GPIO_MAX31855DO], \ +// "DO-State:", digitalRead(pin[GPIO_MAX31855DO]), \ +// "RAW-Data:", MAX31855_ShiftIn(32), \ +// "Probe-Temp:", probetemp, "Internal-Temp:", referencetemp, "Error:", MAX31855_Result.ErrorCode); +// } + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns39(byte function) +{ + boolean result = false; + if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ + + switch (function) { + case FUNC_INIT: + MAX31855_Init(); + break; + case FUNC_EVERY_SECOND: + MAX31855_GetResult(); + break; + case FUNC_JSON_APPEND: + //MAX31855_ShowDebug(); + MAX31855_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + MAX31855_Show(false); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_MAX31855 \ No newline at end of file