So many interruptions today. Luckily I have a smart phone so I have two ways of getting here.
Here is so far before I finish coding. It may look funny, but what you need to know is:
the time base is the scan cycle about 800ms time it takes to read a DS.
it uses the native data from the DS. Shifu in your code your minor temp increments should be .0625, the native resolution of a DS, that way you don't create a setpoint which will never exist in real life only a bracketed value which means it will always hunt.
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
#include <LCDKeypad.h>
LCDKeypad lcd;
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
//Define Variables we'll be connecting to
double targetTemp, Input, Output;
Servo myservo;
float Temp;
// define some variables
int lcd_key = 0;
int adc_key_in = 0;
int P = 0;
int I = 0;
int D = 0;
int set_I = 0;
int set_P = 1;
int set_D = 2;
int set_C = 2;
int CONTROL_DIRECTION = 0;
int Direction = REVERSE;
int SELECT_BUTTON = 0;
PID myPID(&Input, &Output, &targetTemp,P,I,D, Direction ); // tuning parameters
int cursor_pos = 1;
bool NORMAL = false;
bool setPID = true;
bool get_PID = false;
// Defining button used by the lcd keypad
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// Reflux object constants.
#define TEMP_BUFFER_SIZE 32
#define DALLAS_UNINIT 0x0550
#define DALLAS_READERROR -127
struct {
int start_temp; // what temp do we activate cooling?
int set_temp; // what is our setpoint temperature
int raw_temp; // stuff the value in here.
int current_temp; // what is the current temp after after processing
CircularBuffer temp_history(TEMP_BUFFER_SIZE);
CircularBuffer control_history(TEMP_BUFFER_SIZE);
int current_position; // where is the valve
int output_zero; // what value turns valve off_type
int output_max; // what value is maximum cooling
int step; // what direction increases cooling
int crack; // how big a jump to open valve from closed
int sample_size; // how many readings to average must be in 1,2,4,8,16
int max_delta; // clip value for temperature changes to ignore bad inputs
int sensor_errors; // counter for sensor errors.
bool init,learning; // first time flag
} REFLUX = {};
rc REFLUX;
// my control functions
void Reflux_Init (int output_zero, int output_max, int step, int crack, int sample_size,int max_delta,int settle_time)
{
}
int Filter_Value (int intemp);
{
int last_temp, delta_t;
last_temp = rc.temp_history.getElement(0);
if (intemp == DALLAS_READERROR){
rc.sensor_errors++;
return last_temp;
}
delta_t = abs(last_temp-intemp);
if (delta_t > rc.max_delta) {
if (intemp == DALLAS_UNINIT) {
rc.sensor_errors++;
return last_temp;
} else {
return intemp;
}
} else {
return intemp;
}
};
int Reflux_Compute (int target,int current_temp)
{
if (!rc.init) {
rc.current_temp = Filter_Value(rc.raw_temp);
int old_avg = temp_history.averageLast(min(sample_size,temp_history.recordLength()));
temp_history.pushElement(rc.raw_temp);
int new_avg = temp_history.averageLast(min(sample_size,temp_history.recordLength()))
if (new_avg <> old_avg) {
if rc.current_temp == rc.set_temp) {
rc.learning = false;
}
if (rc.current_temp > rc.set_temp){
} else {}
} else {
return 0;
}
} else {
temp_history.pushElement(rc.raw_temp);
rc.current_temp = Filter_Value(rc.raw_temp);
rc.init = FALSE;
}
return 0:
void Button_Input()
{
switch (lcd.button()) {
case KEYPAD_LEFT:
delay(100);
targetTemp = targetTemp - 0.1;
if(targetTemp<1){targetTemp=0;}
lcd.setCursor(0,1);
lcd.print("T:");
lcd.print(targetTemp);
break;
case KEYPAD_RIGHT:
delay(100);
targetTemp = targetTemp + 0.1;
if(targetTemp>98){targetTemp=99;}
lcd.setCursor(0,1);
lcd.print("T:");
lcd.print(targetTemp);
break;
case KEYPAD_DOWN:
delay(100);
targetTemp = targetTemp - 10;
if(targetTemp<1){targetTemp=0;}
lcd.setCursor(0,1);
lcd.print("T:");
lcd.print(targetTemp);
break;
case KEYPAD_UP:
delay(100);
targetTemp = targetTemp + 10;
if(targetTemp>98){targetTemp=99;}
lcd.setCursor(0,1);
lcd.print("T:");
lcd.print(targetTemp);
break;
}
delay(100);
}
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // reading the button value from the lcd keypad
// checking which button is pressed
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP; //250
if (adc_key_in < 380) return btnDOWN; //450
if (adc_key_in < 555) return btnLEFT; //650
if (adc_key_in < 790) return btnSELECT; //850
return btnNONE; // when all others fail, return this...
}
void setup()
{
Serial.begin(9600);
lcd.begin(16, 2); // start communication with LCD keypad shield
targetTemp = 26; //temperature to set to in degrees F
rc.set_temp = targetTemp * 16;
rc.start_temp = (rc.set_temp - 2) * 16; // what temp do we activate cooling?
rc.raw_temp = 0; // stuff the value in here.
rc.current_temp = 0; // what is the current temp after after processing
rc.current_position = 0; // where is the valve
rc.output_zero = 0; // what value turns valve off
rc.output_max = 180; // what value is maximum cooling
rc.step = 1; // what direction increases cooling
rc.crack = 5; // how big a jump to open valve from closed
rc.sample_size = 4; // how many readings to average must be in 1,2,4,8,16
rc.max_delta = 3; // clip value for temperature changes to ignore bad inputs
rc.sensor_errors = 0; // counter for sensor errors.
rc.init = TRUE; // first time flag
rc.learning = TRUE;
myservo.attach(3); //the pin for the servo control
myservo.write(rc.output_zero); //set initial servo position if desired
}
void loop(){
Serial.print(targetTemp); Serial.print(", ");
sensors.requestTemperatures();
Temp = sensors.getTempCByIndex(0);
Serial.print(Temp); Serial.print(", ");
//PID section
Input = Temp;
myPID.Compute();
int invOutput = map(Output, 0, 180, 180, 0); //need to map 0 to 180 to reverse the output from the PID // Output, 0, 180, 180, 0 //180, 0, 0, 180
Serial.println(Output);
myservo.write(invOutput);
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key)
{
case btnSELECT:
{
delay(300);
SELECT_BUTTON = SELECT_BUTTON + 1;
if(SELECT_BUTTON == 4) {SELECT_BUTTON = 0;}
break;
}
}
Serial.println(SELECT_BUTTON );
if (SELECT_BUTTON == 0) {
NORMAL_CONDITION();
// Serial.println("NORMAL");
}
else if (SELECT_BUTTON == 1) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
}
else if (SELECT_BUTTON == 2) {
set_PID();
// Serial.println("set_PID");
}
else if (SELECT_BUTTON == 3) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
}
}
// This function is for normal one
void NORMAL_CONDITION()
{
lcd.setCursor(0,1);
lcd.print("T:");
lcd.print(targetTemp);
lcd.setCursor(0,0);
lcd.print("C:");
lcd.print(Temp);
lcd.setCursor(8,1);
lcd.print("A:");
lcd.print(Output);
Button_Input();
lcd.setCursor(0,0);
lcd.print("C:");
lcd.print(Temp);
lcd.setCursor(8,1);
lcd.print("A:");
lcd.print(Output);
}
// This function will set the PID perimeters
void set_PID(){
lcd.setCursor(0, 0);
lcd.print("PID :");
lcd.setCursor(1, 1);
lcd.print("P:");
lcd.print(P);
lcd.setCursor(6, 1);
lcd.print("I:");
lcd.print(I);
lcd.setCursor(11, 1);
lcd.print("D:");
lcd.print(D);
lcd.setCursor(13, 0);
lcd.print("C:");
lcd.setCursor(0,1);
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
// if right button is pressed, then move the cursor to minutes
case btnRIGHT:
{
delay(250);
cursor_pos++;
if(cursor_pos > 4){cursor_pos = 4;}
break;
}
// if left button is pressed, then move the cursor to hours
case btnLEFT:
{
delay(250);
cursor_pos--;
if(cursor_pos <= 0){cursor_pos = 1;}
break;
}
// if up button is pressed, add 1 to the minutes or hours
case btnUP:
{
delay(150);
if(cursor_pos == 2){
I++;
lcd.setCursor(6, 0);
lcd.print("(I)");
if(I > 98){
I = 99;
}
}
else if(cursor_pos == 1){
P++;
lcd.setCursor(6, 0);
lcd.print("(P)");
if(P > 98){
P = 99;
}
}
else if(cursor_pos == 3){
D++;
lcd.setCursor(6, 0);
lcd.print("(D)");
if(D > 98){
D = 99;
}
}
else if(cursor_pos == 4){
CONTROL_DIRECTION++;
lcd.setCursor(6, 0);
lcd.print("DIR");
if(CONTROL_DIRECTION > 1){
CONTROL_DIRECTION = 1;
lcd.setCursor(13, 0);
lcd.print("C:");
lcd.print((char)62 );
Direction = DIRECT;
}
}
break;
}
// if down button is pressed, minus 1 from the minutes or hours
case btnDOWN:
{
delay(150);
if(cursor_pos == 2){
I--;
lcd.setCursor(6, 0);
lcd.print("(I)");
if(I <= 0){
I = 0;
}
}
else if(cursor_pos == 1){
P--;
lcd.setCursor(6, 0);
lcd.print("(P)");
if(P <= 0){
P = 0;
}
}
else if(cursor_pos == 3){
D--;
lcd.setCursor(6, 0);
lcd.print("(D)");
if(D <= 0){
D = 0;
}
}
else if(cursor_pos == 4){
CONTROL_DIRECTION--;
lcd.setCursor(6, 0);
lcd.print("DIR");
if(CONTROL_DIRECTION <= 0){
CONTROL_DIRECTION = 0;
lcd.setCursor(13, 0);
lcd.print("C:");
lcd.print((char)60 );
Direction = REVERSE;
}
}
break;
}
case btnNONE:
{
break;
}
}
}