Code check and help for still output water

I would greatly appreciate if some one could look at my code and point out what I don't need or where it can be simplified.

I have an arduino uno, terminal shield and a 16x2 lcd shield all stacked.

I will be completely honest here, I have cut, shut merged and modified some codes to do what I require.

Overview = check and control output water temperature from a reflux still.

Water on at 52 degrees C (temperature normal), water on faster at 55 degrees C (temperature hot) and water off at below 50 degrees C (temperature cold).

Servo connected directly to tap and calibrated to be closed at 120 degrees(servo angle) (cold), open fast at 40 degrees(servo angle) and normal flow at 70 degrees (servo angle).

LCD reads Temp Now @(current temp from dallas 18b20 with 4k7 resistor) and Temp Set @ 50-55. If temperature travels over 65 degrees lcd will display CHECK WATER.

I have road tested the above with the tap setup for my still and a cup of hot water for the temp and can confirm it works.

Problems,

I have an external power supply plugged in to the arduino but the lcd flashes upon update/refresh even with and without the usb plugged in. (I will get a new one better suited)

The servo jitters even when at room temp 28 degrees C.

Sometimes it loses the plot over 55degrees with the lcd becoming scrambled and the servo looses the plot too. I guess its my code.

I will be using this temperature based code for a couple of other things too being in the hot Australian climate.

Also take it easy on me as its my first challenge of arduino and code for me.

Thank you,

Russell.

#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal.h>

int DS18S20_Pin = 3;        // Set temperature sensor in pin 0
int thresholdcold = 50;     // Threshold for cold temperature
int thresholdhot = 55;      // Threshold for hot temperature
int thresholdnormal = 52;  // Threshold for normal temperature
int servocold = 120;        // ***** Water should be off ******
int servohot = 40;           // **** water flow approx 1200ml per minute ****
int servonormal = 70;       // *** normal water flow eg. 700ml per minute ***
//int servotrickle = 100;       // *** trickle water flow eg. 200ml per minute ***
int previousPosition = 70;
int ServoDelay = 0;      // Servo delay
int led = 13;              // Red LED
int Relay_Pin = 12;     //only if required **** not used for this application****

LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );

Servo servo1;

float Temp1 = 0;
float Temp2 = 0;
float AverageTemp = 0;

#define ONE_WIRE_BUS 3// Data wire is plugged into pin 3 on the Arduino

OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)

DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.



void setup()
{
  Serial.begin(9600); // Begin communicating with computer

  servo1.attach(10); // Attaches servo to specified pin

  pinMode(13, OUTPUT);
  //pinMode(12, OUTPUT);

}

void loop() {

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  // Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");

  Serial.print("Temperature for Device 1 is: ");
  Serial.println(sensors.getTempCByIndex(1)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire

  // delay(2000);

  Temp1 = sensors.getTempCByIndex(1);           //Store sensor 1 value
  Temp2 = sensors.getTempCByIndex(0);           //Store sensor 2 value

  AverageTemp = (Temp1 + Temp2) / 2;            //Average value of sensor 1 & sensor 2

  Serial.print("Average temp is...");
  Serial.println (AverageTemp);

  lcd.begin( 16, 2 );
  //Print some initial text to the LCD.
  lcd.setCursor( 0, 0 );   //top left
  //          1234567890123456
  lcd.print( "Temp Now @:"); lcd.println(sensors.getTempCByIndex(1));
  //
  lcd.setCursor( 0, 1 );   //bottom left
  //          1234567890123456
  lcd.print( "Temp Set @:50-55");

  if (Temp1 > 65 || Temp2 > 65 ) {

    lcd.clear();
    lcd.print( "**CHECK WATER**");

    digitalWrite(led, HIGH);                                                        // Testing spikes

    Serial.println ("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  }

  delay(200);


  if (AverageTemp <= thresholdcold) // If temperature is above the threshold, activate sequence
  {

    if (servocold != previousPosition) {

      for (previousPosition != 0; previousPosition < servocold; previousPosition += 1) // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }

      servo1.write(servocold);
      previousPosition = servocold;
    }
  }

  else if (AverageTemp >= thresholdhot) // If temperature is above the threshold, activate sequence
  {

    if (servohot != previousPosition) {

      for (previousPosition != thresholdhot; previousPosition -= 1;) // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }
      servo1.write(servohot);
      previousPosition = servohot;


    }

    digitalWrite(led, HIGH);
    digitalWrite(Relay_Pin, HIGH);
  }





  else if (AverageTemp >= thresholdnormal) // If Fract is above the threshold, activate sequence
  {

    while (previousPosition != servonormal) {

      if (previousPosition < servonormal)  // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition++) ;             // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }

      else  // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition--);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }
      servo1.write(servonormal);

      previousPosition = servonormal;

      digitalWrite(led, LOW);
      digitalWrite(Relay_Pin, LOW);
    }


  }

}

This does not belong in your loop function. It sould be in your setup function. Therefore only being called once.

  lcd.begin( 16, 2 );

sensors.getTempCByIndex(1)Is called 3 times. Call it once and put the value in a variable then use the variable later in the program. At the moment you are using a mixture of reading at the point the value is required and using a variable.

      for (previousPosition != 0; previousPosition < servocold; previousPosition += 1) // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }

      servo1.write(servocold);

Why the for loop, particularly when ServoDelay is zero ? Just write the required target angle to the servo in one statement. It does not even matter if the servo is already at the target position. You could at least make the comments match the code.

  if (AverageTemp <= thresholdcold) // If temperature is above the threshold, activate sequenceThe code does not match the comment. Which is correct ?

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf?

Thanks..Tom.................. :slight_smile:

I'm surprised this works:

    Serial.println ("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

I was under the impression that three exclamation points in a row causes a problem for the bootloader - apparently not in this case - perhaps it's not an issue in later versions. Still rather a waste of memory though.

You could make the code rather easier to read by removing some of the blank lines - particularly where there are multiples.

Since you went to the trouble of defining led. This:
  pinMode(13, OUTPUT);
might as well be:

  pinMode(led, OUTPUT);

Again, just for ease of reading, get rid of commented out code, unused code and odd comments e.g.:

  //          1234567890123456
  Serial.println ("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

or

Serial.print("ERROR");
for (int x = 0; x < 46; x++)
{
  Serial.print("!");
}
Serial.println();

Only joking, of course !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

I was under the impression that three exclamation points in a row causes a problem for the bootloader - apparently not in this case - perhaps it's not an issue in later versions.

Obviously, OP is not using a Mega. Only the Mega is affected by the !!! issue.

Thank you all for your comments.

I have modified my code with the above changes (i think) and simplified it a little.

I would like more of a variable control on the water flow based on temperature but that is a little advanced for me at this stage tho any pointers greatly appreciated.

//13-1-2015
#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal.h>

int DS18S20_Pin = 3;        // Set temperature sensor in pin 0
int thresholdcold = 51;     // Threshold for cold temperature
int thresholdhot = 56;      // Threshold for hot temperature
int thresholdnormal = 53;  // Threshold for normal temperature
int servocold = 120;        // ***** Water should be off ******
int servohot = 10;           // **** water flow approx 1000ml per minute ****
int servonormal = 40;       // *** normal water flow eg. 700ml per minute ***
int previousPosition = 60;
int ServoDelay = 15;        // Servo delay

LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );
Servo servo1;
float Temp1 = 0;

#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(9600); // Begin communicating with computer
  servo1.attach(10); // Attaches servo to specified pin

}

void loop(void) {

  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");

  Serial.print("Temperature for Device 1 is: ");
  Serial.println(sensors.getTempCByIndex(1)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire

  delay(1000);

  Temp1 = sensors.getTempCByIndex(1);           //Store sensor 1 value

  lcd.begin( 16, 2 );
  lcd.setCursor( 0, 0 );   //top left
  lcd.print( "Temp Now @:"); lcd.println(sensors.getTempCByIndex(1));
  lcd.setCursor( 0, 1 );   //bottom left
  lcd.print( "Temp Set @:50-56");

  if (Temp1 > 56 ) {

  }

  if (Temp1 <= thresholdcold) // If temperature is above the threshold, activate sequence
  {

    if (servocold != previousPosition) {

      for (previousPosition != 0; previousPosition < servocold; previousPosition += 1) // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }

      servo1.write(servocold);
      previousPosition = servocold;
    }
  }

  else if (Temp1 >= thresholdhot) // If temperature is above the threshold, activate sequence
  {

    if (servohot != previousPosition) {

      for (previousPosition != thresholdhot; previousPosition -= 1;) // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }
      servo1.write(servohot);
      previousPosition = servohot;

    }

  }

  else if (Temp1 >= thresholdnormal) // If Fract is above the threshold, activate sequence
  {

    while (previousPosition != servonormal) {

      if (previousPosition < servonormal)  // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition++) ;             // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }

      else  // goes from 0 degrees to 180 degrees
      { // in steps of 1 degree
        servo1.write(previousPosition--);              // tell servo to go to position in variable 'pos'
        delay(ServoDelay);                       // waits 15ms for the servo to reach the position
      }
      servo1.write(servonormal);

      previousPosition = servonormal;

    }


  }
}

TomGeorge:
Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf?

Thanks..Tom.................. :slight_smile:

Tom, I am going to do a sketch with fritz i think its called. I have removed leds and relay so now its just temp with 4k7res, servo,uno and lcd and most of that info can be picked off the code above.

Russell.

I am bamboozled what you can distill at 50-55 degrees. Is this the temperature of the condenser water ?

You need to be careful with your floats and ints.

for (previousPosition != 0; previousPosition < servocold; previousPosition += 1) // goes from 0 degre

This is invalid. The first part of a for( ) statement is an initialisation of the loop variable. "previousPosition != 0" is not an assignment, the C parser might read it as something, but probably not useful.

for (previousPosition != thresholdhot; previousPosition -= 1;)

This one is also wrong. You can omit some of the three parts of a standard for statement, but you still have to keep them in the correct order.

You need to be very careful with loops like this. You can get easily trapped into loops which never end. Here is an example:

int control_variable=0 ;

/*  do something with control variable,  it now has the value 42 */


/*  Now I want to increase the control variable until it is 40 */
/*  I forgot, it's already 42 !    */

for ( ; control_variable !=40 ; control_variable++ )
{
    /* Move the servo */
}

This loop won't terminate until some kind of integer overflow/wraparound occurs.

A while loop is going to be more reliable here.