Manipulating a reading

I am wondering the best methodology to do the following:

  1. Read themocouple
  2. If tempx < minimum allowable temperature
  3. Turn on relay
  4. else if tempx > than maximum allowable temperature
  5. Turn off relay

Something like this I would say.

`relayState <- false;
function temperatureControl()
{
targetTemp <- 21.0; // Target temperature
targetHyst <- 0.1; // Hysteresis determining how much over and under target temp it should trigger

if (filteredTemperature < (targetTemp-targetHyst)) // If the temperature is below our target temperature-hysteresis then…
{
if (!relayState)
{
relayState = true;
server.log(“Relay pulled”);
}
}
else if (filteredTemperature > targetTemp+targetHyst) // If the temperature is ablove target temperature+hysteresis then…
{
if (relayState)
{
relayState = false;
server.log(“Relay released”);
}
}

hardware.pin5.configure(DIGITAL_OUT);
hardware.pin5.write(relayState?1:0);

imp.wakeup(0.5, temperatureControl);
}
temperatureControl();`

It also got hysteresis in so the relay won’t flicker around the target temperature. So when it is set to 21c as target temperature, it will be on until temperature is 21.1c, and first turn on again when it drops down to 20.9c

The temperature variable it uses is called “filteredTemperature” in this snippet.

So if I am using this to read the probe would the “tc” be the equivalent of filteredTemperature in your example? Very cool!

function readMash189(){
//Get SPI data
hardware.pin8.write(0); //pull CS low to start the transmission of temp data
//0[31…24],1[23…16],2[15…8],3[7…0]
temp32=hardware.spi189.readblob(4);//SPI read is totally completed here
hardware.pin8.write(1); // pull CS high
// Begin converting Binary data for chip 1
local tc = 0;
if ((temp32[1] & 1) ==1){
//Error bit is set
local errorcode = (temp32[3] & 7);// 7 is B00000111
local TCErrCount = 0;
if (errorcode>0){
//One or more of the three error bits is set
//B00000001 open circuit
//B00000010 short to ground
//B00000100 short to VCC
switch (errorcode){
case 1:
server.log(“TC open circuit”);
break;
case 2:
server.log(“TC short to ground”);
break;
case 3:
server.log(“TC open circuit and short to ground”)
break;
case 4:
server.log(“TC short to VCC”);
break;
default:
//Bad coding error if you get here
break;
}
TCErrCount+=1;
//if there is a fault return this number, or another number of your choice
tc= 67108864;
}
else
{
server.log(“error in SPI read”);
}
}
else //No Error code raised
{
local highbyte =(temp32[0]<<6); //move 8 bits to the left 6 places
local lowbyte = (temp32[1]>>2); //move to the right two places
tc = highbyte | lowbyte; //now have right-justifed 14 bits but the 14th digit is the sign
//Shifting the bits to make sure negative numbers are handled
//Get the sign indicator into position 31 of the signed 32-bit integer
//Then, scale the number back down, the right-shift operator of squirrel/impOS
tc = ((tc<<18)>>18);
// Convert to Celcius
celcius = (1.0* tc/4.0);
// Convert to Farenheit
farenheit = (((celcius*9)/5)+32);
server.log(celcius + “°C”);
server.log(farenheit + “°F”);
}
}

I think “celcius” would be the same as what “filteredTemperature” is in my code.

Ahh ok cool, I will integrate and see how it goes. Thanks for the help!

I am envisioning something like this:

`// assign hardware.pin5 to a global variable
therm <- hardware.pin8;
therm2 <- hardware.pin9;
// configure pin5 to be an ANALOG_IN
therm.configure(ANALOG_IN);
therm2.configure(ANALOG_IN);

// these constants are particular to the thermistor we’re using
// check your datasheet for what values you should be using
const b_therm = 3977.0;
const t0_therm = 298.15;

// the resistor in the circuit (10KΩ)
const R2 = 10000.0;

//set relay variables to off
relaystrikeState <- false;
relaymashState <- false;

function MashTemp_F() {
local Vin = hardware.voltage();

local Vout = Vin * therm.read() / 65535.0;
local R_Therm = (R2*Vin / Vout) - R2;

local ln_therm = math.log(10000.0 / R_Therm);
local temp_K = (t0_therm * b_therm) / (b_therm - t0_therm*ln_therm);

local temp_C = temp_K - 273.15;
local temp_F = temp_C * 9.0 / 5.0 + 32.0;

return mashtemp_F;
}
function StrikeTemp_F() {
local Vin = hardware.voltage();

local Vout = Vin * therm2.read() / 65535.0;
local R_Therm = (R2*Vin / Vout) - R2;

local ln_therm = math.log(10000.0 / R_Therm);
local temp_K = (t0_therm * b_therm) / (b_therm - t0_therm*ln_therm);

local temp_C = temp_K - 273.15;
local temp_F = temp_C * 9.0 / 5.0 + 32.0;

return striketemp_F;
}

function startWarmup() {
// Get and log Fahrenheit temperature
local mashtemp = MashTemp_F();
local striketemp = StrikeTemp_F();
server.log(temp + " F");
server.log(temp2 + " F");
targetMashTemp <- 163; //Target Mash Temperature
targetStrikeTemp <- 168; //Target Strike Temperature
targeHyst <- 0.2; //Hysteresis to avoid Relay jitter

if (striketemp < (targetStrikeTemp-targeHyst))  //Turn on Strike heat
{
	if (!relaystrikeState)
	{
		relaystrikeState = true;
		server.log("Strike Relay Off");
	}
}
	else if (striketemp > (targetStrikeTemp-targeHyst))  //Turn off Strike heat
{
	if (relaystrikeState = false);
	server.log("Strike Relay On");
	}
	
if (mashtemp < (targetMashTemp-targeHyst))  //Turn on Mash circulation pump
{
	if (!relaymashState)
	{
		relaymashState = true;
		server.log("Mash Relay Off");
	}
}
	else if (mashtemp > (targetMashTemp-targeHyst))  //Turn off Strike heat
{
	if (relaymashtate = false);
	server.log("Mash Relay On");
	}
	
mashrelay <- hardware.pinB;
strikerelay <- hardware.pinC;
// configure LED pin for DIGITAL_OUTPUT
mashrelay.configure(DIGITAL_OUT);
strikerelay.configure(DIGITAL_OUT);
hardware.pinB.write(relaystrikeState?1:0);
hardware.pinC.write(relaymashState?1:0);

	
// wakeup in 5 seconds and read the value again:
imp.wakeup(5.0, poll);

}

startWarmup()
`

Try using the code tags, makes it a lot easier to read.

Thanks for the advice!

adding a basic PI’D’ algo would be a nice add-on.

I dont see this compiling at all…

imp.wakeup(5.0, poll);
No function named “poll”

`function MashTemp_F() {
local Vin = hardware.voltage();

local Vout = Vin * therm.read() / 65535.0;
local R_Therm = (R2*Vin / Vout) - R2;

local ln_therm = math.log(10000.0 / R_Therm);
local temp_K = (t0_therm * b_therm) / (b_therm - t0_therm*ln_therm);

local temp_C = temp_K - 273.15;
local temp_F = temp_C * 9.0 / 5.0 + 32.0;

return mashtemp_F;
}`
In here there isn’t any “mashtemp_F”, it should instead be

return temp_F;

Unfortunately it compiles it just doesn’t appear to run. So more like this:

`function MashTemp_F() {
local Vin = hardware.voltage();

local Vout = Vin * therm.read() / 65535.0;
local R_Therm = (R2*Vin / Vout) - R2;

local ln_therm = math.log(10000.0 / R_Therm);
local temp_K = (t0_therm * b_therm) / (b_therm - t0_therm*ln_therm);

local temp_C = temp_K - 273.15;
local mashtemp_F = temp_C * 9.0 / 5.0 + 32.0;

return mashtemp_F;
}
function StrikeTemp_F() {
local Vin = hardware.voltage();

local Vout = Vin * therm2.read() / 65535.0;
local R_Therm = (R2*Vin / Vout) - R2;

local ln_therm = math.log(10000.0 / R_Therm);
local temp_K = (t0_therm * b_therm) / (b_therm - t0_therm*ln_therm);

local temp_C = temp_K - 273.15;
local striketemp_F = temp_C * 9.0 / 5.0 + 32.0;

return striketemp_F;
}`

and

`imp.wakeup(5.0, startWarmup);
}

startWarmup()`

@Chrischi what were you thinking?

Improving-the-beginners-pid-introduction

google PID Controller and brewing

That looks pretty cool, but might be more than I can code just yet. :slight_smile: Here is my basic idea. I have a HERMs system and the current algo is to bring the temperatures up to mash temperatures. Once there, after I add the grain it will turn on and off the circulation pump to keep the mash temp ±1 degree. That will allow me to have the sparge water at the proper heat and save some time in the process.

on long-term view, you will need a PID function to get a constant temp. otherwise it will oscillate around the target temperature.

Ahh I see, its something a bit more complicated than just the hysteresis function @MikeyDK posted. If I understand correctly you basically average the target temperature to keep from firing up the relay unnecessarily.

The reason I got the hysteresis is because I use a mechanical relay for my setup… using PID would cause it to pretty much turn on and off constantly to maintain a temperature. If you use a solid state relay it would be another story though.

I have a 4x SSR relay breakout. I guess I should add PID then eh…