Arduino Development Thread

Australia & New Zealand Homebrewing Forum

Help Support Australia & New Zealand Homebrewing Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
hi Jonathon,



I haven't managed to test mine yet but have written some code (read: bastardised matho's) to pid control the heater, but control cooling on offset and deadband.

I also added a setpoint rate of change calc to enable temp ramping at a set rate. I can post the code when I get home tomorrow night if you like.


Cheers



Dan

Sounds great Dan,
Cheers.
 
Hey Guys,
Save me reading 30 odd pages, has anyone worked on a Fermentation cabinet heating / cooling setup with PID? I have a large fridge I need to control and if someone has started this or knows of code it will save me heaps of time. I have not found any source with both heating and cooling.
Cheers
Jono
That is what I did in my fridge.

Look at something called uberfridge, which is what I based my code on. I have since bastardised the code so much that mine is possibly too specific to my needs, but I would be happy to share it with you, but first read his site and how the code works.
 
As promised Jono,

View attachment Ferment_Controller.txt

As i said before, i haven't fully tested it in anger yet.

Setpoint Rate of change (ROC) is on deg/day, cool min time is minimum on time of cooling out put in seconds (to protect fridge compressor), cool offset is the offset from the setpoint that the fridge will start up and cool hys is the hysteresis for the resetting of the fridge start command.

Up and down buttons will get you to the setup menu, previous and next buttons will get you to the setpoint rate of change override, to allow instant setpoint changes.

Set up to use a DS18B20 temp sensor and 16 x 2 lcd display.

Cheers
Dan
 
As promised Jono,

View attachment 57809

As i said before, i haven't fully tested it in anger yet.

Setpoint Rate of change (ROC) is on deg/day, cool min time is minimum on time of cooling out put in seconds (to protect fridge compressor), cool offset is the offset from the setpoint that the fridge will start up and cool hys is the hysteresis for the resetting of the fridge start command.

Up and down buttons will get you to the setup menu, previous and next buttons will get you to the setpoint rate of change override, to allow instant setpoint changes.

Set up to use a DS18B20 temp sensor and 16 x 2 lcd display.

Cheers
Dan

Fantastic Dan,
Sounds like you have it all covered, will have a play. I owe you a beer or 3. I'll let you know how it goes.
Much Appreciated,
Cheers..
 
Hey guys,

I'm just getting up to speed on Arduino and I've got a bunch of stuff on its way from Deal Extreme (slowly.)

I'm planning on making a controller that will share a single 10A input across my HLT and direct fired RIMS MLT, with PID control on both of them. I've been through matho's code, which I'm starting to understand (not having a coding background) but that's obviously specifically for a single vessel system.

Anybody have any ideas how to "power share" across two PIDs, with the MLT PID having preference over the HLT? Is it as simple as:-

Calculate MLT PID
If result = power on MLT
set HLT element off
set MLT element on
else
set MLT element off
calculate HLT PID
if result = power on HLT
set HLT element on.
end if
end if

If they both have the same PID window size, is that going to clash?

Anybody else tried to do this? I know it's in Brewtroller trunk, but I can't get my head around the code yet.

Cheers,

Jon
 
Hey guys,

I'm just getting up to speed on Arduino and I've got a bunch of stuff on its way from Deal Extreme (slowly.)

I'm planning on making a controller that will share a single 10A input across my HLT and direct fired RIMS MLT, with PID control on both of them. I've been through matho's code, which I'm starting to understand (not having a coding background) but that's obviously specifically for a single vessel system.

Anybody have any ideas how to "power share" across two PIDs, with the MLT PID having preference over the HLT? Is it as simple as:-

Calculate MLT PID
If result = power on MLT
set HLT element off
set MLT element on
else
set MLT element off
calculate HLT PID
if result = power on HLT
set HLT element on.
end if
end if

If they both have the same PID window size, is that going to clash?

Anybody else tried to do this? I know it's in Brewtroller trunk, but I can't get my head around the code yet.

Cheers,

Jon

Hey Jon,

I'm no expert, but my bet would be to duplicate all the pid code and add some code to fire the HLT in period of the window not used by the MLT. In the PID_HEAT function maybe something like this:


myPID.Compute();
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
digitalWrite(HeatHLT,LOW);
}

if((OutputMLT*(WindowSize/100)) > now - windowStartTime)
{
digitalWrite(HeatMLT,HIGH);
HLTwindowStartTime = now; //New unsigned long variable to note last time of MLT heating
}
else {
digitalWrite(HeatMLT,LOW);
if((OutputHLT*(WindowSize/100))>now - HLTwindowStartTime) digitalWrite(HeatHLT,HIGH);
else digitalWrite(HeatHLT,LOW);
}


The bold text is stuff i've added. May need some fine tuning but i reckon something similar to this should work. HLT will lose heat when MLT output is high, which is to be expected.

Cheers
Dan
 
Evening Jon,
I'm interested to see what you come up with, as I'm planning on doing something similar by butchering Matho's code. It won't happen until after Xmas due to other commitments though. :angry:
I've converted two kegs with a common spigot so that I can transfer the malt pipe (similar to ArnieW BrauBushka) from one to the other after mash out and then recirc the preheated sparge water from the second keg through the drained malt pipe and hopefully get better efficiencies and maintain the clean wort. Partigyle(??) brewing has also sprung to mind by doing high grav in first keg and using the second keg to boil the lower grav sparged second keg. This would also require repetitive switching or a delay to the start of the second boil.
The main keg has 3kW and the second 2.5kW and I was hoping to run it off a single 15A line with switching between the two. I can't see any issues other than my programming!!
To ensure both aren't on at the same time I was going to try and incorporate a checking loop so that keg 1 always overrides keg 2, but keg 1 can't kick in until after keg 2 has been turned off. I'm sure this will stuff with the accuracy of the PID control slightly, but I'd rather not run a second power cord on another circuit, and it's a challenge!!

Good luck and I'll follow your progress with interest.

Cheers BB
 
Look at this, stm32 dev board with 2.8" touch screen LCD for < $30 delivered.

http://www.ebay.com/itm/STM32F103RBT6-deve...=item3a68965ee7
Thanks for posting that, waiting for mine to arrive. I've been using an AVR but it's a bit too small to talk directly to a webserver. Agree that arduino dev tools are simpler though.

In the interim I've got my AVR controlling the fermentation fridge, STC-1000 style but with graphs on a webpage and a bit more overshoot control. For the mains-control part rather than SSRs I got a remote control power socket and wired in an optocoupler to control the relay's transistor. Be careful though, even the "low voltage" bits are referenced to the mains high side... For $10 a socket it's cheaper than building an enclosure, and it's a nice size.

I was originally going to control it with a 433mhz RF module but that's a bit too unreliable for something as important as fermentation!
 
Thanks for posting that, waiting for mine to arrive.

Cool, some others are interested in these so I'm putting together a Ubuntu VirtualBox image with the toolchain installed and setup, a simple FreeRTOS example project with touch and LCD drivers working and an easy to use menu framework.

Might not be quite a simple as arduino but should be easy enough to get going.
 
Cool, some others are interested in these so I'm putting together a Ubuntu VirtualBox image with the toolchain installed and setup, a simple FreeRTOS example project with touch and LCD drivers working and an easy to use menu framework.

Might not be quite a simple as arduino but should be easy enough to get going.
Yeah thanks again for that Matt. :icon_cheers:

I've got one of these on my desk and can see the potential but just didn't know where to start. Good to hear others are experimenting too.
 
I'm interested to see what you come up with, as I'm planning on doing something similar by butchering Matho's code....

Here's what I've come up with so far. I knocked this up in notepad rather than the IDE, so syntax may well be wrong. I'm really just thinking through the logic.

Code:
void ControlHeat() {

  // Control heat output based on PID calculations

  // MLT takes preference over HLT



  PID_WINDOW_SIZE = 5000; // this lives in the variable declarations, not in the main loop.

  unsigned long NOW = millis();



  // If the HLT is enabled, calculate the PID output



  if HLT_HEAT_ENABLED && ((HLT_TEMP_SETPOINT - HLT_TEMP_CURRENT) > 5.0) {		   // HLT's heating but we're more than 5deg below setpoint

	HLT_PID_OUTPUT = PID_WINDOW_SIZE;								// = window size

	}

  else if HLT_HEAT_ENABLED && ((HLT_TEMP_SETPOINT - HLT_TEMP_CURRENT) < 5.0) {	// HLT's heating but we're LESS than 5deg below setpoint  

	HLT_PID.Calculate();

	}

  // else HLT PID isn't enabled

  end if



  // Do the same as above for the MLT

  // If the MLT is enabled, calculate the PID output



  if MLT_HEAT_ENABLED && ((MLT_TEMP_SETPOINT - MLT_TEMP_CURRENT) > 5.0) {		   // MLT's heating but we're more than 5deg below setpoint

	MLT_PID_OUTPUT = PID_WINDOW_SIZE;								// = window size

	}

  else if MLT_HEAT_ENABLED && ((MLT_TEMP_SETPOINT - MLT_TEMP_CURRENT) < 5.0) {	// MLT's heating but we're LESS than 5deg below setpoint  

	MLT_PID.Calculate();

	}

  // else MLT PID isn't enabled

  end if



  if (NOW - PID_WINDOW_START_TIME) > PID_WINDOW_SIZE)) {  // If we've past the end of a window, roll it over to start again

	PID_WINDOW_START_TIME += PID_WINDOW_SIZE;			// Put a debug in here to log window increment

	}



  if (MLT_HEAT_ENABLED && ! HLT_HEAT_ENABLED) {			// MLT is ON, but HLT is OFF

	if (MLT_PID_OUTPUT > (NOW - PID_WINDOW_START_TIME)) {   // Output within window

	  digitalWrite (HLT_HEAT,LOW);					// switch HLT off...

	  digitalWrite (MLT_HEAT,HIGH);					// then switch MLT on.

	  }

	else

	  digitalWrite (MLT_HEAT,LOW);					// switch MLT OFF.

	end if;



  else if (HLT_HEAT_ENABLED && ! MLT_HEAT_ENABLED) {			// HLT is ON, but MLT is OFF

	if (HLT_PID_OUTPUT > (NOW - PID_WINDOW_START_TIME)) { // Output within window

	  digitalWrite (MLT_HEAT,LOW);					// switch MLT off...

	  digitalWrite (HLT_HEAT,HIGH);					// then switch HLT on.

	  }

	else

	  digitalWrite (HLT_HEAT,LOW);					// switch HLT OFF.

	end if;





  else if (HLT_HEAT_ENABLED && MLT_HEAT_ENABLED) {				// Both enabled: HLT is ON, AND MLT is ON

	if (MLT_PID_OUTPUT > (NOW - PID_WINDOW_START_TIME)) { // Output within window

	  digitalWrite (HLT_HEAT,LOW);					// switch HLT off...

	  digitalWrite (MLT_HEAT,HIGH);					// then switch MLT on.

	  }

	else if ((MLT_PID_OUTPUT + HLT_PID_OUTPUT) > (NOW - PID_WINDOW_START_TIME)) { // Output within window

	  digitalWrite (MLT_HEAT,LOW);					// switch MLT off...

	  digitalWrite (HLT_HEAT,HIGH);					// then switch HLT on.

	  }

	else

	  digitalWrite (HLT_HEAT,LOW);					// switch HLT OFF.

	  digitalWrite (MLT_HEAT,LOW);					// switch MLT OFF.

	end if;



  else // Neither HLT nor MLT enabled

	  digitalWrite (HLT_HEAT,LOW);					// switch HLT OFF.

	  digitalWrite (MLT_HEAT,LOW);					// switch MLT OFF.



  end if;



}
 
Cheers for posting that Jon.
I've had a quick look through it and I can see that your logic covers some of the issues I was having with guaranteeing the switching but still preferencing the mash.
It will be a good base to start with when I finally get around to working on my rig again.

BB
 
Anybody know why matho's got this line in his PID_HEAT function:-

Code:
if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH);

Specifically, why he's using Output*(WindowSize/100) rather than just Output as per the PID examples?

Cheers,

Jon
 
Anybody know why matho's got this line in his PID_HEAT function:-

Code:
if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH);

Specifically, why he's using Output*(WindowSize/100) rather than just Output as per the PID examples?

Cheers,

Jon
Because we're controlling an on off heating element. we need to determine the duty cycle. Straight output is for controlling motors and the like that can be controlled via a motor controller etc.
 
Because we're controlling an on off heating element. we need to determine the duty cycle. Straight output is for controlling motors and the like that can be controlled via a motor controller etc.

Thanks Bonj. So output is a percentage rather than a fixed value between 0 and Windowsize?
 
Thanks Bonj. So output is a percentage rather than a fixed value between 0 and Windowsize?
To be honest, I don't actually know. I assume it is a percentage or an 8-bit value between 0 and 255 or similar. Whatever the actual value, it tells the rest of the code how often to switch the element on and for how long.
 
To be honest, I don't actually know. I assume it is a percentage or an 8-bit value between 0 and 255 or similar. Whatever the actual value, it tells the rest of the code how often to switch the element on and for how long.

I did a bit of debugging, and the output value returned is a a value between the output limits i.e. between 0 and WindowsSize in this case.

I'll put my code up on github when I work out how. I'm pretty happy with the power sharing code - seems to work pretty well at this point. Now I just need the LCD to arrive so I can start work on the UI.
 
Back
Top