Pump speed controlled by temperature with an LCD to monitor the temp swell

Hi

My project is to the control the speed of a pump by monitoring water temperature. I need to keep a set temperature in a distilling tower and this is done by pumping water through the tower. If the temperature climbs the water flow needs to increase, if the temperature drops the water flow needs to drop to bring the temp back to what i want to maintain. I also want to incorporate an LCD to monitor the temp as well.

materials I have

Arduino UNO
MAX6675 K-type thermocouple
Dual H-Bridge motor controller
compatible Hitachi HD44780 16x2 LCD
12v pump

I have found some code from someone else that has just used the MAX and the motor controller without the LCD incorporated into the code.

I am having trouble bringing the 2 together

So my question is, is this possible to bring the 2 together and what way would I go about it?

Thanks

Caleb

Did your professor give you any other requirements ?

what you ask is simple, but often there are other requirements that make it more difficult.

to get this done. research your display and get it to work. should not take more than an hour. get the libraries, etc.

add temperature input and watch that change the display.

add your control output for the pump and then fine turn it so you are satisfied with the results.

Where is that code you found? You're right. Adding LCD after the code has already been written may be difficult, especially if the code was not written in a way to accept user values, such as temperature.

Thanks for your Help

Ill have a play around with some of the example code and make sure everything works first before I bring it all together.

Liudr, Here is a copy of the code i found:

#include "max6675.h"

int thermoDO = 6;
int thermoCS = 7;
int thermoCLK = 8;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int vccPin = 3;
int gndPin = 2;
  
void setup() {
  Serial.begin(9600);
  // use Arduino pins 
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  pinMode(10, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(2, OUTPUT); // for buzzer
  
  Serial.println("MAX6675 test");
  // wait for MAX chip to stabilize
  delay(500);

  digitalWrite(13,HIGH); // pump rotation direction
  digitalWrite10,LOW); // pump rotation direction
  analogWrite(9,150);
  delay(1000);
}

void loop() {
  // basic readout test, just print the current temp
  
   Serial.print("C = "); 
   Serial.println(thermocouple.readCelsius());
   float temperature = thermocouple.readCelsius();
 
  digitalWrite(13,HIGH); // pump rotation direction
  digitalWrite(10,LOW); // pump rotation direction
  digitalWrite(2,LOW); // For Buzzer
    
     
     if(temperature < 49){ //  Set Low Temperature
        analogWrite(9,80);
     }
     if(temperature > 49 and temperature < 51){ 
        analogWrite(9,80);
     }
     if(temperature > 51 and temperature <= 53){ 
        analogWrite(9,85);
     }
     if(temperature > 53 and temperature <= 55){ 
        analogWrite(9,90);
     }
     if(temperature > 55 and temperature <= 57){ 
        analogWrite(9,90);
     }
     if(temperature > 57 and temperature <= 59){ 
        analogWrite(9,95);
     }
     if(temperature > 59 and temperature <= 61){ 
        analogWrite(9,100);
     }
     if(temperature > 61 and temperature <= 63){ 
        analogWrite(9,110);
     }
     if(temperature > 63 and temperature <= 65){ 
        analogWrite(9,125);
     }
     if(temperature > 65 and temperature <= 66){ 
        analogWrite(9,140);
     }
     if(temperature > 66 and temperature <= 67){ 
        analogWrite(9,150);
     }
      if(temperature > 67 and temperature <= 69){ 
        analogWrite(9,175);
        digitalWrite(2,HIGH);
     }
     if(temperature > 67){ 
        digitalWrite(2,HIGH); // For Buzzer
     }

     if(temperature > 67){ // Set Low Temperature
        analogWrite(9,200);
     }
         
   delay(1000);
}

Thanks again

Caleb

You need to replace all of the magic numbers such as 66, 67, 69 etc with variables if you want to have a user set these values. That's the first step to get from fixed numbers to some variable ones. Next, you need to find a way to add a user interface that arduino will not be stuck waiting for user to change numbers. Because that would mean the temperature is no longer being senses and pump is no longer changing speed. The term is non-blocking code.

Ok Thanks

I didn't really need to change the variable.

I want to maintain a set temperature of 55 degC +/1 2 degC

so that was my idea with the magic numbers (temperatures) and the pump speed (Percentages)

would this work, or have i got it all wrong?

I want to maintain a set temperature of 55 degC +/1 2 degC
so that was my idea with the magic numbers (temperatures) and the pump speed (Percentages)
would this work, or have i got it all wrong?

 if(temperature > 53 and temperature <= 55){ 
        analogWrite(9,90);
     }
     if(temperature > 55 and temperature <= 57){ 
        analogWrite(9,90);
     }

You have a range of 4 degrees where the pump is running at the same speed. This does not seem correct for the .5 degree control you desire. I think that tuning your system for the pump speed required when the temperature is not at 55 will be harder than adding an LCD to display the temperature.

How have you characterized your system, and where did the temperature/pump speed numbers come from? Designing a proportional controller will require knowledge of the system.

I don't see any issues with adding a display.

I would recommend that you look at the "Blink without Delay" example in the IDE and also at the tutorial
"Demonstration code for several things at the same time" . You will be better off if you replace the delay(1000) with a millis() based timer to control the updating of the display and the reading of a new temperature.

What then, is the purpose of the LCD? I know you need to display temperature and pump speed. This is easy, replace serial.print with lcd.print and mind the fact the LCD cursor needs to be moved from line 1 to line 2 since it doesn't move by itself.

Then do you also want a user to make any changes? Maybe I misunderstood you.

Liudr

The LCD is just to watch the temp as a peace of mind really while it is all running.

No, the user won't need to make any changes once i am happy with the code and how it run's.

when I change the serial.print to lcd.print, do I also have to section off the 2 seperate bits of code or create seperate loops to have the pump control running + the lcd at the same time?

Cattledog

I was assuming there will be a lot of trial and error to tune the pump control when i get it all setup and running to see how it responds and the accuracy that I really need.

I will look at those to items and get familiar with them.

thanks

Caleb

I've uploaded the example sketch that came with MAX6675 library, I've changed the pins to the ones i am using and uploaded it to the controller.

When I verify the sketch I get a "WARNING: Spurious .github folder in 'MAX6675 library' library"

Should this still work, or does this need to be rectified?

the other Problem I get is, when I upload the sketch and run the serial to check the temps I get C=nan and F=nan. (no temp readings at all).

Also, i didn't see and info about what to set the vcc and and pins to?

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int vccPin = 3;
int gndPin = 2;

Thanks

Caleb

there is a huge gap that needs to be considered.

Please understand that my writing is not meant to insult as unless you have had a year of controls, this is all new and you are learning on the job. You are EXPECTED to make mistakes. We are expected to both educate you and guide to a workable final system.

using your car, can you say that having your foot on the gas exactly half way down will result in exactly a set speed ?
the answer is without reservation NO
your powers of observation have dozens of sensors and you have one of the greatest microprocessors above your shoulders. An ANT is an Arduino in comparison. Your disadvantage is that you can process so many things so fast, you assume the Arduino has just as many inputs and just as much adaptive control.

your process is a simple loop. circulate water from one place where you add cooling to one place where it gets hot and your only options here are to either have variable control of cooling with a fixed flow rate, or have a variable flow rate with fixed cooling.

if you just recirculate the water it will get hot and alter the process as you will then need more fluid to remove more BTU from the distillation tower.

cooling the water can be an entire separate control system with all the complexities of a control system, or it could be tap water and have very slow temperature changes.

back to your process. it would be good if you sketched out your process and showed every part. go on-line and search for a generic layout to get ideas how things might work.

but at this point, you have a pump and a temperature sensor.

although you will probably wind up with a PI control and mis-name it a PID control, you can get a good grasp on control by doing individual steps.

set-point or SPV for set point value. that is your desired value. No reason you cannot change it on the fly, but since you do not care to at this point, we hold that for later.

PV or process value, that is what you are measuring, in your case the local temperature at the sensor. this is also called sensor temperature. separate in your mind the notion that sensor temperature has anything to do with water temp or process temp, it is only sensor temp. placement of the sensor and selection of the sensor are vital to an accurate reading.

at this point, you have not discussed a flow sensor, therefore we can assume you do not have one. so, you are running your pump speed by means of an open loop ( this means UN-measured) however, your sensor temp feeds back a value that you want to believe has anything to do with the pump output. (shut off the heat to the distillation tower and watch the temperate change without any pump flow)

but, when a lot of assumptions are made and put into place, the system does some things and you can alter them and see changes. this is how many systems are started. you get it to do something, then figure out what is the worst part and fix that, then there is a new worst part, and every time you take the old worst part off the top of the list, there is a new top of the list. it is the nature of the beast.

so, what I propose you consider is that you measure the temperature and then alter the pump speed based on that measurement.

dave-in-nj

Thanks heaps for your write up, and no insult taken, i am very new to Arduino and coding.

What you propose is exactly what i am trying to achieve, A continuous loop of measuring the sensor temp and altering the pump speed to suit, with a rough delay with each measurement to give the change in water to have affect.

At the moment the cooling on the still uses a constant flow of tap water with a little valve in line that I have to adjust by hand depending on the temperature on the returning water. This involves about 4 hours of sitting and babysitting the still. I am trying to eliminate having to devote 4 hours of 100% monitoring and only have to keep a eye on it when i am happy with the setup.

The reservoir of water will be cooled by and old water chiller. So the water will be pumped in through the distillation tower and returned to the water chiller. So the speed of the pump will control the flow of this water and the temperature will be taken as the water exits the tower.

I will do up a drawing so the whole circuit is graphically shown and easy to see.

The code I have attached in one of my earlier posts is from a guy that was doing the same thing. I have altered his temperatures as I want a cooler nominal temp and I also changed the pins to what i am using.
Im not sure on the quality of the code as i am new to this but i have seen it working.

thanks

Caleb

what control does is look at the difference of where you are and where you want to be. we call that error or off-set

ERROR = PV - SV // [find the difference between where you are and where you want to be ]

// error = process value less set-point value

this will be either a positive number or a negative number, and on very rare occasions, it will be 0

int SV = 50 ; // fixed value of 50.00000 degrees, can be changed in programming
int rawSensor = A0 // temperature sensor into pin A0
int ERROR ; // a global variable
int PV ; // a global variable.
int PumpSpeed = 0 ;

ERROR = PV - SV ;

// timer function
delay(1);
timer = timer + 1; // increments once every 1 mS

if( error >= 10){ // WAY off
if (timer > = 1000 ) { // once a second
PumpSpeed = PumpSpeed + 1 ;
timer=0; // reset the timer
}
}

if( error >= 2){ // off but not horrible
if (timer > = 5000 ) { // once ever 5 seconds
PumpSpeed = PumpSpeed + 1 ;
timer=0; // reset the timer
}
}
}

if( error >= 0.2){ // almost dead on
if (timer > = 10000 ) { // once ever ten seconds
PumpSpeed = PumpSpeed + 1 ;
timer=0; // reset the timer
}
}

as you can see that is only to speed up the pump and does not allow to slow it down.
this is crude, but should show you how you can break it into manageable pieces.
you might find that only 2 stages are needed, or that you want 5... as you can see, you can pick things.

the delay is blocking, but not really blocking too much to be in the way.

this is a pseudo fuzzy logic. it uses bands of error on the sensor, but does not react, or over-react like proportional does.

this has fixed times. if you wanted to clean it up, you can add integral to set the times, and then only need to have one of these loops.

INTEGRAL=INTEGRAL + ERROR ;
have to be a long because if the error is large it will jump to a million in seconds.
if ( integral > 100000) ; // if you lose EVERY instance of delay () use a small number like 1 million to start
// this will not work if you use any delay anywhere in your program.

so :

INTEGRAL=INTEGRAL + ERROR ;

if ( INTEGRAL > 100000) ;
pulse = HIGH;
INTEGRAL = 0 ; // ================= ADDED
}

if (pulse = = HIGH ) { // once every time the cumulative error counts up to 1 million
PumpSpeed = PumpSpeed + 1 ;
pulse = LOW;
}

if the error is way off, it will increase pump speed a couple times a second.
if the error is getting close, it will take many seconds to increase pump speed
if you are very close, some values may go negative and it could take minutes
once you are almost dead on, the number of error over and error under should keep the count from ever reaching 1 million
and (hopefully) no change for hours.

I am not saying this is the best solution, but rather here is a look at how you can make it work with what you have without getting krazy.

as a note, say your sketch ran the loop 1 million times a second. your count would roll over once per second for every degree you were off. if you were off 5 degrees, then it would roll over 5 times a second.

OK, physical things.

valves come in many types. a globe valve, a gate valve, a needle valve
each has it's uses.
some valves are horrible for control. a motorized ball valve is great for on/off but is horrible for accurate control.
they do make a proportioning ball valve that is good, but hard to find and expensive.

a needle valve is very sloow, but is much more accurate for control

please do not think you can put a super high accurate motor on a piece of crap valve.
you are much better off by getting a valve designed for control in your range of flow.

plumbing valves are about 50 years behind the technology we use in electronics and HVAC controls are 100 years behind !

often a valve that is 10% open will deliver 90% of the flow.
that means you should start with a valve that delivers your required volume at about 80% of your pressure. that would mean you have some ability to control.

based on your comment, I would expect that you only need some simple control loops and a decent control valve.

as an experiment, can you connect a tube to your column and open your valve fully
then get a smaller tube, and a smaller tube until your fully open valve will not allow enough flow ?
then you would know the maximum port size for a valve. you may be surprised how small it is.

as a comment, you could use 10 tiny tubes and 10 solenoid valves and turn them on and off. A a tiny tube would have some small effect. and using say, 3 medium and 3 small would offer some control of flows
just tossing out an idea.

OK, another post.....

you say you are controlling a valve, but you discuss a pump.....

if you use a pump, you circulate water, or re-circulate water...

your process as far as the water is concerned is heat transfer. your reservoir will get warm with the added BTU's extracted from the distillation column. sooner or later you will need to remove those BTU's. if you do that abruptly, it will effect the values in the column.

you would not want to change the water temperature faster than the effect it would have on the column, or more correctly, faster than you can adjust for the effects it has.

now I can see why ice baths would be considered, the amount of energy in phase change has no effect on temperature. just like glaciers regulated the Earth's temps until about 20,000 year ago when they receded and exposed the land beneath, once you lose that regulation of phase change, and the unimaginable amount of energy it took to make those glaciers, you have a run-away process. sorry.... had an aligned technology that seems to parallel this.

running water to exchange the heat in the reservoir is an option.
a second control system to regulate that temperature might be fun to have as well.

sorry for writing a paper...
I did go back and make some small edits to correct spelling or grammar or clarify.

also, my comments were generic in nature.
my PV (process variable) and SV (setpoint variable) were never extracted from temperature.
the correct way would be to :
#1) select a temperature sensor/probe/houseing and circuitry that can resolve readings of more resolution than you want to control. your sensor should be capable of betwen 4 and 10 times more resolution than your final control resolution.
#2) take the raw values from your sensor into degrees or some engineering units in the sketch
#3) use the temperature values for the math for the control.

the Arduino has a 10 bit analog input, pretty poor for any resolution. there are a few ways to get far better resolution.
sensor selection and location have a lot to do with good, or bad final control.

Thanks again for your great input, thats a lot of info you have shared for me.

the valve at the moment is a manual needle valve.

I was going to use a pump and control the speed via PWM instead of controlling a needle valve via a stepper motor because i will need the pump anyway and I thought the code would be simpler. i am going to still have the needle valve in the loop as well but just as a bit of a restrictor if needed.

The water will be going into the distillation tower at the same temperature all the time as i am going to use the compressor and heat sink parts out of an old water bubbler that delivers ice cold water to drink. I was going to use radiators and fans but i didn't think they would drop the temperature enough unless i had a huge setup.

With The code that i was going to use, are you saying this wouldn't work and I should look at what you have posted in your earlier post with the errors.

Thanks

Caleb

slattery_caleb:
With The code that i was going to use, are you saying this wouldn't work and I should look at what you have posted in your earlier post with the errors.

Thanks

Caleb

glad to hear you have put so much thought into this and have some much of the parts in place.

as for the extant code, no, it is not viable.

pump rate is dependant on energy transfer, not temperature.

assuming that your temperature intput is great.

I did not see how you get temperature, but :

const int pumpPin = 9 [  // selects pin 9 for pump ouput


// #include "max6675.h"

int thermoDO = 6;
int thermoCS = 7;
int thermoCLK = 8;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
int vccPin = 3;
int gndPin = 2;

int  SV = 55 ;  // fixed value of 55.00 degrees, can be changed in programming
int ERROR ;   // a global variable
int PV ;  // a global variable.
int PumpSpeed = 80 ;  //  set initial value of 80 




 
void setup() {
 Serial.begin(9600);
 // use Arduino pins 
 pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
 pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
 pinMode(10, OUTPUT);
 pinMode(13, OUTPUT);
 pinMode(pumpPin, OUTPUT);
 pinMode(2, OUTPUT); // for buzzer
 
 Serial.println("MAX6675 test");
 // wait for MAX chip to stabilize
 delay(500);

 digitalWrite(13,HIGH); // pump rotation direction
 digitalWrite(10,LOW); // pump rotation direction
 analogWrite(9,150);
 delay(1000);
}

void loop() {
 // basic readout test, just print the current temp
 
  Serial.print("C = "); 
  Serial.println(thermocouple.readCelsius());
  float temperature = thermocouple.readCelsius();

 digitalWrite(13,HIGH); // pump rotation direction
 digitalWrite(10,LOW); // pump rotation direction
 digitalWrite(2,LOW); // For Buzzer
   

//=====================================


PV = temperature ;

ERROR = PV - SV ;

// timer function
delay(1);
timer = timer + 1;  // increments once every 1 mS

if( error >=  1.0 ){    // close to 
  if (timer > = 1000 ) {  // once a second
       PumpSpeed = PumpSpeed + 1 ;
       timer=0;  // reset the timer
  }
}

if( error >=  -1.0 ){    // close to 
  if (timer > = 1000 ) {  // once a second
       PumpSpeed = PumpSpeed - 1 ;
       timer=0;  // reset the timer
  }
}

//  ===============  OUTPUT

analogWrite(pumpPin,PumpSpeed); // control pump 

}  // end of void loop

as for the starting points. you should start your pump at the place you expect it to run.
in your previous you were between 80 and 100 so I used 80

within a few minutes, things will settle out. since your process is really almost flat, all you need to do is keep it between the rails. you should be able to get a good feel for the starting flow rate in rather short order.

I am not familiar with the library or the sensor, so have to rely on that being workable as you have it.
since I do not have the library, the above would not compile for me.

but it should allow you to run the pump.

if this works, then we need to add the LCD library.

if you get \357 error, that means there is some stray space character.
I think it is in my ending brackets of the if() statements.

I commented out sections and removed 2 blank spaces.

going to order one of the 6675 thermocouples. only has 1.5 C accuracy, but has 0.25C resolution.

not sure how good that is with the 10 bit ADC input. I would think there are much more sensitive and accurate sensors for the narrow window needed for this project.

as a note, you could use a 3-way valve and recirculate ambient temp for any length of time. then slowly allow cold to be added until it was full cold water. 'start-up' procedures are wholly different than running and in some cases, take just as much effort with software and hardware.

as you flush this out with your LCD and such, consider adding additional sensors. cold water, pump output temp, column output temp, flow rate ,. calculate BTU based on flow and temp.

considering I got up at 3:00 AM and you responded, either your sleep is messed up, you work overnight, or you live in a part of the globe in which the sun rises at a different time.

I am off to work. check back in 12 to 14 hours.
Dave

Hi Dave

Thanks again for all your help, very much appreciated.

Im in Australia, not sure where you are, but it is just past mid night here, last post before bed.

I was having a play around with the example sketch that came with MAX6675 library, I've changed the pins to the ones i am using and uploaded it to the controller.

When I verify the sketch I get a "WARNING: Spurious .github folder in 'MAX6675 library' library"

Should this still work, or does this need to be rectified?

Ive done a bit of searching and haven't found a fix yet.

The other Problem I get is, when I upload the sketch and run the serial to check the temps I get C=nan and F=nan. (no temp readings at all).

I haven't figured out what this problem could be yet, any ideas?

The sensor i am using is a K-type and it will be placed right where the cooling water exits the column. I have noticed with the manual setup i am running currently, from when i adjust the needle valve (and the water flow changes) to when the water hits the thermometer at the water exit (i see a temperature change) is about 5 to 10 seconds.

would this delay need to be taken into account?

Thanks heaps for the sketch, ill upload it to the controller as soon as i get a chance.

something else I tried to program into my sketch was to have the pump running while the boiler in the still gets the wash up to boilingtemperature and the "cooling water" chiller gets the water cold ready to go, this process takes about an hour. I wanted to do this for 2 reasons. firstly for when the wash reaches boiling point and the column is at the correct temperature for producing alcohol, i wanted the column at an even temperature and maintained. The second reason is to prevent the heat sink of the chiller freezing with the cooling water constantly flowing through the cooling system and the heat sink.
This was what i was trying to achieve with "temperature >47 run the pump at 80%"

Thanks again for you help

Caleb