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

I have attached to PDF drawings.

A000001 is a Electrical Schematic of the Arduino Boards showing pin outs
A000002 is a Process Diagram of the Still and Temperature Controller.

Any pointers or improvements are greatly appreciated.

Thanks
Caleb

A000002_Upload.pdf (110 KB)

A000001_Upload.pdf (89.8 KB)

slattery_caleb:
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?

yes, it would have to be rectified. if there is an issue with the library, there will be problems.
check the sensor data sheet to see if there are specifics or of there is a requiremetn to use analolg pins and not digital pins.

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 would suspect that this is an extension of the first fault. if your library is not set to read the correct pins, it only makes sense that you get no values.

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?

absolutely. this time lag would and should be part of the timing values.
maybe use a 10 second test and not 1 second.

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%"

this all should be simple to do. you could add a second switch for 'pre-heat' and 'run' so while in pre-heat the pump runs constantly and then under 'run' the system goes to the control point

.
If you take CS low during a conversion, it’ll stop the conversion that’s already in progress. I seem to recall it’ll just return the previous value in this case. So, don’t read faster than about 4Hz.

that means you cannot read the temp ever looop. also, the chip is a ADC in ti's own with on-board amp for the K thermocouple. that means you get around the low resolution ADC in the Arduino.

I took a look at some of the information on the web about the Turbo 500 still. The system looks pretty well designed and characterized. Some flow rate/temperature information is given. I think you will be very successful using an Arduino to control this syste.

Are you using the temperature sensors which come with the system?

Any pointers or improvements are greatly appreciated.

Obviously, fixing the MAX6675 library problem and getting temperature readouts is the first thing.

I suggest that the next thing you do is characterize the pump curve and determine flow rates at the different duty cycles. The pump output may not be linear, and its not clear to me that the 4.3 l/min is a good fit the the pre cool rate of 450ml/min suggested for water under 25C.

You may also find that the motor is very noisy and you might want to change the pwm frequency.

You may already have collected flow rate/temperature data from your valved operation and once you characterize the pump you can make the conversion.

Another way to help tune the system, you may want to write some code which controls the PWM duty cycle with keyboard input from a laptop connected to the arduino. Then you can then perform a manually controlled run, and take some data on temperatures and duty cycles. You might even want to log a run with temperature/duty cycle data logged to an SD card or collected to a file on the PC with a terminal program like RealTerm.

This sounds like a fun project, but late night programming after sampling the results might need revision in the morning.

Hi Dave

I have fixed the temperature reading problem. the Chinese didn't cut off the insulation on the thermocouple when that terminated connectors on the end. So that works correctly and I can now see temperatures when i check the serial port.

I am having trouble getting you code to pass the verify stage. The error i am getting is

"expected ',' or ';' at end of input"

and it has the last line highlighted, everything I've tried i can't clear that error.

The other error it is getting is

"expected primary-expression before 'class'"

I haven't been able to work this one out either.

Cattledog

yes it is a great system and won't require much change in water flow once it is stable.

I am going to a needle valve to assist in setting the base flow and then leave the PWM pump to do the rest.

I will have a play around with the PWM code and see what frequency will be required to achieve the recommended starting flow rate.

Thanks again gents for your support.

Caleb

slattery_caleb:
Hi Dave

I am having trouble getting you code to pass the verify stage. The error i am getting is

"expected ',' or ';' at end of input"

"expected primary-expression before 'class'"

in order to get it to compile, I had to comment out some lines
since I do not have the library that you have, or the sensor, I cannot test this.

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


// #include "max6675.h"    // **************  commented out

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

// MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);       // **************  commented out
int vccPin = 3;
int gndPin = 2;

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

int timer ; 
int error ;

 
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());    // **************  commented out
//  float temperature = thermocouple.readCelsius();   // **************  commented out

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

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


// PV = temperature ;         // **************  commented out

P_ERROR = PV - SV ;

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

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

if( P_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

not sure how to you want to handle the buzzer.
since your project has at least two stages.
#1) warm-up
#2) running

you may want to have a set of parameters for over-temp with alarm in all cases
but under-temp only when running
and also include operational temp as a slow beep during the warm-up.

Hi Dave

I got that to compile. Ill upload it to the controller tomorrow and bench run it for a trial with the pump.

Will that be hard to add the LCD component to that code if it works?

Earlier this afternoon, I was trialling different PWM signals on the pump to see how it runs with some pretty basic code. the pump didn't really like much below 150, and it looked to start above 200.

I'm going to play with my needle valve as a restrictor, so i can keep the pump up higher in the PWM range.

Thanks
Caleb

slattery_caleb:
Earlier this afternoon, I was trialling different PWM signals on the pump to see how it runs with some pretty basic code. the pump didn't really like much below 150, and it looked to start above 200.

that does not sound promising. means you have from 200 to 256 as your full scale ?

if you have the old needle valve set up from your prior use, you can fill a 1 litre container with a stopwatch.... well, use a stopwatch as you fill the container with water anyway.

find how many litres per minute you have used in the past.

that would be the output of the pump you need to get.

I would venture to say that the pump would need to be able to pump less than that, and of course more than that. the idea is that you need a throttling range that will allow you to have control.

you may be able to put a cap on the pump with a small hole and get less flow, but more pressure.

Hi Dave

Yes, Im going to have to get a smaller pump, it pumps way to much water, and if i restrict it at all it just stops. with a PWM signal of 110 i did get it to 600mL/min but its unreliable and sometimes stops. also at that low rate its only getting 3v from the pump controller.

Ive been playing around with your code, Ive used the pump speed values (initial and error correction) and the error correction temps for the purpose of the exercise to test the code and so i can visually see the flow change when i alter the temp of the sensor.

it runs the pump fine at what ever initial pump speed I use, but it onset seem to alter it depending if I raise or lower the temp either side of the 55degC.

Also if I run the serial monitor the readout of the current temp does not change from the initial reading when I start the serial monitor.

Thanks

Caleb

slattery_caleb:
it runs the pump fine at what ever initial pump speed I use, but it onset seem to alter it depending if I raise or lower the temp either side of the 55degC.

Also if I run the serial monitor the readout of the current temp does not change from the initial reading when I start the serial monitor.

sorry, not enough coffee to understand what you are saying.

as for the serial monitor, post you code

mabybe that word is 'doesen't' ? "doessent.."... does not ?

serial print the temperature
make sure you see a temperature change when you hold your hand on the sensor.

added some serial print at the end.
shows tempeature, and the results of the calculation.

const int pumpPin = 9 ;  // selects pin 9 for pump output

// #include "max6675.h"    // **************  commented out

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

// MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);       // **************  commented out
int vccPin = 3;
int gndPin = 2;

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

int timer ;
int error ;


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());    // **************  commented out
  //  float temperature = thermocouple.readCelsius();   // **************  commented out

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


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


  // PV = temperature ;         // **************  commented out

  P_ERROR = PV - SV ;

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

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

  if ( P_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



  Serial.print("PV= ");
  Serial.print(PV);
  Serial.print(" SV= ");
  Serial.print(SV);
  Serial.print(" P_ERROR= ");
  Serial.println(P_ERRPR);
  

}  // end of void loop

not sure how much flow you need, but, you could put a bucket above your unit and connect a pipe to allow water to drain.
use gravity as the force to allow water to flow.

two problems. flow rate depends on height of bucket and also depth of water. fill the bucket and the water pressure is higher, allow it to drain and the water pressure is lower, flow rate will change.

There are ways to make that work better. such as two buckets, one you fill, that drains into the second bucket. the second has an overflow that allows any extra to drain back into your resource, the overflow controls level..

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

When the actual temperature is cooler than the set point; P_ERROR is a negative value, and I think this should be

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

cattledog:

P_ERROR = PV - SV ;
if ( P_ERROR >=  -1.0 ) {  // close to

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




When the actual temperature is cooler than the set point; P_ERROR is a negative value, and I think this should be



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

you would be correct.
one has to be true when the number is positive, the other when it is negative.

I think he has to change the timer as well. the process has an inherent delay of at least 10 seconds for anything to register after a control change.

just a thought...

to get your constant temperature, why not control your heater rather than the cooling?

Might be more efficient if that matters to you

regards

Allan.

allanhurst:
just a thought...

to get your constant temperature, why not control your heater rather than the cooling?

Might be more efficient if that matters to you

regards

Allan.

when distilling alchol, you have to boil the liquid. then cool the steam/vapors. so the heating is no the problem that needs to be controlled. the chilled section is the key. and, if everything is working well, any changes will be slow.

I would think that a mid-point sensor would be a good thing to have to have a faster feedback.

Hi Dave

sorry, not enough coffee to understand what you are saying.

it runs the pump fine at what ever initial pump speed I use, but it onset seem to alter it depending if I raise or lower the temp either side of the 55degC.

The pump will run at the initial speed, but it doesn't seem to alter the speed to correct the temp error. Im using a heat gun and a glass of cold water to simulate altering the temperature.

here is the code for the serial problem. its just the original code you gave me but I altered the pump speeds and the temperatures for the purpose of the exercise.

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


#include "max6675.h"    // **************  commented out

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

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);       // **************  commented out
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 = 255 ;  //  set initial value of 80 

int timer ; 
int error ;

 
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);
 
 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,255);
 delay(1000);
}

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

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

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


PV = temperature ;         // **************  commented out

ERROR = PV - SV ;

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

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

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

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

analogWrite(pumpPin,PumpSpeed); // control pump 

}  // end of void loop

I haven't had a chance to try the new code you gave me so I don't know if that has fixed it but the problem was that each time I started the serial monitor tool it keeps continuously displaying the initial temp reading when the serial monitor tool was opened, (its not updating as I warm up or cool down the sensor). So I'm not sure if this is the problem with the program to it doesn't update the temperature.

Thanks again for all your help. Ill give that code run when I get a chance. Im searching for a new pump as well.

Thanks Caleb

Please note that Cattledog pointed out I did not have the second if() correct.

I also fixed a type on my variables. I cannot use ERROR as it is a function.
I changed every case to P_ERROR for process error.

here it is with some notes at the top

/* changed to 12 second delay on control
corrected negative if() to show less than
changed  ERROR  to P_ERROR
 
 */

const int pumpPin = 9 ;  // selects pin 9 for pump output


#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 P_ERROR ;   // Process Error a global variable
int PV ;  // a global variable.
int PumpSpeed = 80 ;  //  set initial value of 80

int timer ;
int error ;


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 ;

  P_ERROR = PV - SV ;

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

  if ( P_ERROR >=  1.0 ) {  // close to setpoint
    if (timer >= 12000 ) {  // once every 12 seconds
      PumpSpeed = PumpSpeed + 1 ;
      timer = 0; // reset the timer
    }
  }

  if ( P_ERROR <=  -1.0 ) {  // close to setpoint
    if (timer >= 12000 ) {  // once every 12 seconds
      PumpSpeed = PumpSpeed - 1 ;
      timer = 0; // reset the timer
    }
  }

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

  analogWrite(pumpPin, PumpSpeed); // control pump


  Serial.print("PV= ");
  Serial.print(PV);
  Serial.print(" SV= ");
  Serial.print(SV);
  Serial.print(" P_ERROR= ");
  Serial.println(P_ERROR);


}  // end of void loop

the problem was that each time I started the serial monitor tool it keeps continuously displaying the initial temp reading when the serial monitor tool was opened, (its not updating as I warm up or cool down the sensor).

You must solve this problem. Have you ever gotten valid and changing data from the sensor when you use the example program which come with the library?

I'm not familiar with the max6675 but I think it better to only do one reading

Serial.println(thermocouple.readCelsius());
  float temperature = thermocouple.readCelsius();

Revision

 float temperature = thermocouple.readCelsius();
Serial.println (temperature);