moelski wrote:@bertb:
zo I reworked the code a bit.
Did you put update the github code?
No, I do not know how to. Besides, it's far from decent. I only changed the MAX31855 part.
Per haps one of the real programmers can take it to the next level.
As long as you do not have a MAX31855 with the K- connected to ground, as I do, you will not need to ignore errors.
I also took out the SPI init lines as this is already done by ESPEasy and I show the cold junction temperature.
It works very good for me.
Here is my stuff:
Code: Select all
//#######################################################################################################
//######################## Plugin 120: Thermocouple (MAX6675 / MAX31855) ################################
//#######################################################################################################
// Plugin Description
// This Plugin reads the data from Thermocouples. You have to use an Adapter Board with a
// MAX6675 or MAX31855 in order to read the values. Take a look at ebay to find such boards :-)
// You can only use ESP8266 boards which expose the SPI Interface. This Plugin uses only the Hardware
// SPI Interface - no software SPI at the moment.
// But neverless you need at least 3 Pins to use SPI. So using an very simple ESP-01 is no option - Sorry.
// The Wiring ist straight forward ...
//
// If you like to send suggestions feel free to send me an email : dominik@logview.info
// Have fun ... Dominik
// Wiring
// https://de.wikipedia.org/wiki/Serial_Peripheral_Interface
// You need an ESP8266 device with accessable SPI Pins. These are:
// Name Description GPIO NodeMCU Notes
// MOSI Master Output GPIO13 D7 Not used (No Data sending to MAX)
// MISO Master Input GPIO12 D6 Hardware SPI
// SCK Clock Output GPIO14 D5 Hardware SPI
// CS Chip Select GPIO15 D8 Hardware SPI (CS is configurable through the web interface)
// Thermocouple Infos
// http://www.bristolwatch.com/ele2/therc.htm
// Chips
// MAX6675 - Cold-Junction-Compensated K-Thermocouple-to-Digital Converter ( 0°C to +1024°C)
// https://cdn-shop.adafruit.com/datasheets/MAX6675.pdf (only
// MAX31855 - Cold-Junction Compensated Thermocouple-to-Digital Converter (-270°C to +1800°C)
// https://cdn-shop.adafruit.com/datasheets/MAX31855.pdf
//#include <SPI.h>
#define PLUGIN_120
#define PLUGIN_ID_120 120
#define PLUGIN_NAME_120 "Temperature Thermocouple"
#define PLUGIN_VALUENAME1_120 "Temperature C"
#define PLUGIN_VALUENAME2_120 "Temperature K"
uint8_t Plugin_120_SPI_CS_Pin = 15; // D8
uint16_t Plugin_120_SensorError;
double Plugin_120_HJ_Temp = 0.0;
double Plugin_120_CJ_Temp = 0.0;
uint16_t Plugin_120_IgnoreError;
boolean Plugin_120(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_120;
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
Device[deviceCount].VType = SENSOR_TYPE_DUAL; // 2 Messwerte
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 2;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_120);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_120));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_120));
break;
}
case PLUGIN_INIT:
{
// Get CS Pin
// If no Pin is in Config we use 15 as default -> Hardware Chip Select on ESP8266
if (Settings.TaskDevicePin1[event->TaskIndex] != 0)
{
// Konvert the GPIO Pin to a Dogotal Puin Number first ...
Plugin_120_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
}
// set the slaveSelectPin as an output:
pinMode(Plugin_120_SPI_CS_Pin, OUTPUT);
// initialize SPI:
// SPI.setHwCs(false);
// SPI.begin();
addLog(LOG_LEVEL_INFO, (char*)"P120 : SPI Init");
success = true;
break;
}
case PLUGIN_WEBFORM_LOAD:
{
string += F("<TR><TD>Info GPIO:<TD><b>1st GPIO</b> = CS (Usable GPIOs : 0, 2, 4, 5, 15)");
byte choice1 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
String options[2];
options[0] = F("MAX 6675");
options[1] = F("MAX 31855");
//options[2] = F("MAX 31865");
int optionValues[2];
optionValues[0] = 1;
optionValues[1] = 2;
//optionValues[2] = 3;
string += F("<TR><TD>Adapter IC:<TD><select name='plugin_120_maxtype'>");
for (byte x = 0; x < 2; x++)
{
string += F("<option value='");
string += optionValues[x];
string += "'";
if (choice1 == optionValues[x])
string += F(" selected");
string += ">";
string += options[x];
string += F("</option>");
}
string += F("</select>");
byte choice2 = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
String options2[4];
options2[0] = F("None");
options2[1] = F("All");
options2[2] = F("SCV");
options2[3] = F("SCG");
int optionValues2[4];
optionValues2[0] = 0;
optionValues2[1] = 7;
optionValues2[2] = 4;
optionValues2[3] = 2;
string += F("<TR><TD>Ignore error:<TD><select name='plugin_120_error'>");
for (byte x = 0; x < 4; x++)
{
string += F("<option value='");
string += optionValues2[x];
string += "'";
if (choice2 == optionValues2[x])
string += F(" selected");
string += ">";
string += options2[x];
string += F("</option>");
}
string += F("</select>");
byte choice3 = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
String options3[2];
options3[0] = F("Celsius");
options3[1] = F("Fahrenheit");
int optionValues3[2];
optionValues3[0] = 1;
optionValues3[1] = 2;
string += F("<TR><TD>C/F:<TD><select name='plugin_120_cf'>");
for (byte x = 0; x < 2; x++)
{
string += F("<option value='");
string += optionValues3[x];
string += "'";
if (choice3 == optionValues3[x])
string += F(" selected");
string += ">";
string += options3[x];
string += F("</option>");
}
string += F("</select>");
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
String plugin1 = WebServer.arg("plugin_120_maxtype");
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
String plugin2 = WebServer.arg("plugin_120_error");
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
String plugin3 = WebServer.arg("plugin_120_cf");
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
success = true;
break;
}
case PLUGIN_READ:
{
// Get the MAX Type (6675 / 31855)
// TBD ... Auswertung je nach Chip !!!
byte MaxType = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
Plugin_120_IgnoreError = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
byte viewcf = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
// Get CS Pin
// Konvert the GPIO Pin to a Dogotal Puin Number first ...
Plugin_120_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
switch (MaxType) {
case 1: // MAX6675
Plugin_120_HJ_Temp = readMax6675();
break;
case 2: // MAX31855
Plugin_120_HJ_Temp = readMax31855();
break;
case 3: // MAX31865 (not implemented yet)
//do something when var equals 2
break;
}
if (Plugin_120_HJ_Temp != NAN)
{
if (viewcf == 1)
{
UserVar[event->BaseVarIndex] = Plugin_120_HJ_Temp;
UserVar[event->BaseVarIndex + 1] = Plugin_120_CJ_Temp;
}
else
{
UserVar[event->BaseVarIndex] = CelsiusToFahrenheit(Plugin_120_HJ_Temp);
UserVar[event->BaseVarIndex + 1] = CelsiusToFahrenheit(Plugin_120_CJ_Temp);
}
String log = F("P120 : HJ : ");
log += UserVar[event->BaseVarIndex];
log += F(" - CJ : ");
log += UserVar[event->BaseVarIndex + 1];
addLog(LOG_LEVEL_INFO, log);
success = true;
}
else
{
UserVar[event->BaseVarIndex] = NAN;
UserVar[event->BaseVarIndex + 1] = NAN;
String log = F("P120 : No Sensor attached !");
addLog(LOG_LEVEL_INFO, log);
success = false;
}
break;
}
}
return success;
}
double readMax6675()
{
uint16_t rawvalue = 0;
// take the SS pin low to select the chip:
digitalWrite(Plugin_120_SPI_CS_Pin, LOW);
// String log = F("P120 : CS Pin : ");
// log += Plugin_120_SPI_CS_Pin;
// addLog(LOG_LEVEL_INFO, log);
// "transfer" 0x0 and read the Data from the Chip
rawvalue = SPI.transfer16(0x0);
// take the SS pin high to de-select the chip:
digitalWrite(Plugin_120_SPI_CS_Pin, HIGH);
String log = F("P120 : MAX6675 : RAW - BIN:");
log += String(rawvalue, BIN);
log += " HEX:";
log += String(rawvalue, HEX);
log += " DEC:";
log += String(rawvalue);
addLog(LOG_LEVEL_DEBUG, log);
// Open Thermocouple
// Bit D2 is normally low and goes high if the thermocouple input is open. In order to allow the operation of the
// open thermocouple detector, T- must be grounded. Make the ground connection as close to the GND pin
// as possible.
Plugin_120_SensorError = !(rawvalue & 0x0004);
if (Plugin_120_SensorError)
{
// Shift RAW value 3 Bits to the right to get the data
rawvalue >>= 3;
// Calculate Celsius
return rawvalue * 0.25;
}
else
{
return NAN;
}
}
double readMax31855()
{
uint16_t hrawvalue = 0;
uint16_t crawvalue = 0;
// take the SS pin low to select the chip:
digitalWrite(Plugin_120_SPI_CS_Pin, LOW);
// "transfer" 0x0 and read the MSB Data from the Chip
hrawvalue = SPI.transfer16(0x0);
// Shift MSB 16 Bits to the left
// rawvalue <<= 16;
// "transfer" 0x0 and read the LSB Data from the Chip
crawvalue = SPI.transfer16(0x0);
// take the SS pin high to de-select the chip:
digitalWrite(Plugin_120_SPI_CS_Pin, HIGH);
// D0,1,2 - This bits read at 1 when any of the SCV, SCG, or OC faults are active. Default value is 0.
Plugin_120_SensorError = (crawvalue && 0x0007);
hrawvalue >>= 2;
crawvalue >>= 4;
String log = F("P120 : MAX31855 : hRAW - BIN:");
log += String(hrawvalue, BIN);
log += " HEX:";
log += String(hrawvalue, HEX);
log += " DEC:";
log += String(hrawvalue);
log += F(" : cRAW - BIN:");
log += String(crawvalue, BIN);
log += " HEX:";
log += String(crawvalue, HEX);
log += " DEC:";
log += String(crawvalue);
addLog(LOG_LEVEL_DEBUG, log);
if (Plugin_120_IgnoreError==7 | Plugin_120_SensorError==Plugin_120_IgnoreError)
{
// Data is D[31:18]
// Shift RAW value 18 Bits to the right to get the data
// Check for negative Values
// +25.00 0000 0001 1001 00
// 0.00 0000 0000 0000 00
// -0.25 1111 1111 1111 11
// -1.00 1111 1111 1111 00
// -250.00 1111 0000 0110 00
if (hrawvalue & 0x2000) // Bit 31=1 -> neg Values
{
// Negate all Bits
hrawvalue = ~hrawvalue;
// Add 1 and make negative
hrawvalue = (hrawvalue + 1) * -1;
}
if (crawvalue & 0x800) // Bit 31=1 -> neg Values
{
// Negate all Bits
crawvalue = ~crawvalue;
// Add 1 and make negative
crawvalue = (crawvalue + 1) * -1;
}
// Calculate Celsius
Plugin_120_CJ_Temp=(crawvalue * 0.0625);
// Calculate Celsius
return hrawvalue * 0.25;
}
else
{
return NAN;
}
}
// Convert Celsius to Fahrenheit
double CelsiusToFahrenheit(double celsius) {
return celsius * 9.0 / 5.0 + 32;
}
/*double cJuntionTemp() {
}*/