Created
December 9, 2017 19:32
-
-
Save DerBierBaron/89ee1b72185f6dbf8f0554607b91a399 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[code] | |
#include <OneWire.h> /*sensor bus library*/ | |
#include <DallasTemperature.h> /*DS18B20 library*/ | |
#include <ShiftedLCD.h> /*to use 74HC595 shift register with LCD*/ | |
#include <SPI.h> | |
#include <PID_v1.h> | |
#include <EEPROM.h> | |
#define CONFIG_VERSION "f01" | |
#define CONFIG_START 25 | |
#define PWM6 OCR4D /*Pin 6 shortcut*/ | |
#define PWM6_MAX OCR4C /*terminal timer count*/ | |
#define RELAIS 7 /*Relais output pin 9*/ | |
#define TARGET_UP 18 /*up button pin 18*/ | |
#define TARGET_DOWN 19 /*down button pin 19*/ | |
#define DBG false | |
#define DEBUG(x) if(DBG && Serial) { Serial.print (x); } | |
#define WAIT 500 | |
#define DUTY_MIN 64 /*minimum fan speed (0...255)*/ | |
#define DUTY_DEAD_ZONE 64 /*delta between minimum output for the PID and DUTY_MIN (DUTY_MIN - DUTY_DEAD_ZONE)*/ | |
#define KP 0.4 | |
#define KI 0.4 | |
#define KD 0.05 | |
const unsigned char One_Wire_Bus = 8; | |
int sensor_count = 0; | |
const unsigned int Latch_Pin = 10; | |
bool lastUp = false, lastDown = false; | |
bool up, down = false; | |
bool blank = false; | |
bool blink = true; | |
unsigned long prev1, prev2, prev3, prev4 = 0; /*time placeholders*/ | |
double duty; | |
double dtemp, ctemp; | |
bool fanRunning = true; | |
struct StoreStruct | |
{ | |
char version[4]; | |
double target; | |
} storage = { | |
CONFIG_VERSION, | |
40 | |
}; | |
PID fanPID(&ctemp, &duty, &storage.target, KP, KI, KD, REVERSE); | |
OneWire oneWire(One_Wire_Bus); /*sensor Pin to Bus*/ | |
DallasTemperature sensors(&oneWire); | |
LiquidCrystal lcd(Latch_Pin); /*initialize LCD shift with latchpin of 74HC595*/ | |
void pwm6configure() /*Configuration PWM clock*/ | |
{ | |
TCCR4A = 0; | |
TCCR4B = 4; /*4 sets 23437Hz*/ | |
TCCR4C = 0; | |
TCCR4D = 0; | |
PLLFRQ = (PLLFRQ & 0xCF) | 0x30; | |
OCR4C = 255; | |
} | |
void pwmSet6(int value) /*Set PWM to D6 (Timer4 D), argument is PWM between 0 and 255*/ | |
{ | |
OCR4D = value; /*set PWM value*/ | |
DDRD |= 1 << 7; /*set Output Mode D7*/ | |
TCCR4C |= 0x09; /*activate channel D*/ | |
} | |
void loadConfig() /*Check if saved bytes have the same "version" and loads them. Otherwise it will load the default values*/ | |
{ | |
if (EEPROM.read(CONFIG_START + 0) == CONFIG_VERSION[0] && | |
EEPROM.read(CONFIG_START + 1) == CONFIG_VERSION[1] && | |
EEPROM.read(CONFIG_START + 2) == CONFIG_VERSION[2]) | |
for (unsigned int t = 0; t < sizeof(storage); t++) | |
*((char*)&storage + t) = EEPROM.read(CONFIG_START + t); | |
} | |
void saveConfig() | |
{ | |
for (unsigned int t = 0; t < sizeof(storage); t++) | |
EEPROM.update(CONFIG_START + t, *((char*)&storage + t)); | |
} | |
void writeTemp(double temp) | |
{ | |
sensors.requestTemperatures(); /*get Temperature*/ | |
temp = sensors.getTempCByIndex(0); | |
lcd.setCursor(10, 0); | |
lcd.print(temp, 1); | |
} | |
void writeTarget() | |
{ | |
lcd.setCursor(10, 1); | |
lcd.print(storage.target, 1); | |
} | |
void writeBlank() | |
{ | |
lcd.setCursor(10, 1); | |
lcd.print(" "); | |
delay(500); | |
} | |
void writeLCD () | |
{ | |
writeTemp(dtemp); | |
if (blank) | |
{ | |
writeBlank(); | |
} | |
else | |
{ | |
writeTarget(); | |
} | |
} | |
void setup() | |
{ | |
Serial.begin(19200);/*start serial connecction to PC*/ | |
if(DBG) | |
{ | |
while (!Serial) {} /*WAIT FOR THE SERIAL CONNECTION FOR DEBUGGING*/ | |
} | |
DEBUG("Fans..."); | |
// pinMode(SPD_IN, INPUT); | |
pinMode(RELAIS, OUTPUT); | |
pinMode(TARGET_UP, INPUT_PULLUP); | |
pinMode(TARGET_DOWN, INPUT_PULLUP); | |
// attachInterrupt(digitalPinToInterrupt(SPD_IN), pickRPM, FALLING); | |
DEBUG("Display..."); | |
pwm6configure(); | |
loadConfig(); | |
DEBUG("PID..."); /*Setup the PID to work with our settings*/ | |
fanPID.SetSampleTime(WAIT); | |
fanPID.SetOutputLimits(DUTY_MIN - DUTY_DEAD_ZONE, 255); | |
fanPID.SetMode(AUTOMATIC); | |
DEBUG("Fans..."); | |
pwmSet6(255); /*Let fan run for 5s*/ | |
delay(5000); | |
lcd.begin(16, 2); /*set up LCD's columns and rows*/ | |
lcd.print("Temp.: "); | |
lcd.setCursor(14, 0); | |
lcd.print((char)223); | |
lcd.setCursor(15, 0); | |
lcd.print("C"); | |
lcd.setCursor(0, 1); | |
lcd.print("SET-Temp.:"); | |
lcd.setCursor(14, 1); | |
lcd.print((char)223); | |
lcd.setCursor(15, 1); | |
lcd.print("C"); | |
DEBUG("Sensor..."); | |
sensors.begin(); | |
sensor_count = sensors.getDeviceCount();/*check number of attached sensors*/ | |
DEBUG("Ready.\n\n"); | |
prev1 = millis(); | |
} | |
void loop() | |
{ | |
unsigned long cur = millis(); | |
bool shouldPrint = false; | |
lastUp = up; | |
lastDown = down; | |
up = !digitalRead(TARGET_UP); | |
down = !digitalRead(TARGET_DOWN); | |
prev3 = cur; | |
sensors.requestTemperatures(); | |
double t = sensors.getTempCByIndex(0); | |
if (!isnan(t)) | |
{ | |
dtemp = round(t * 2.0) / 2.0; | |
ctemp = round(t); | |
} | |
fanPID.Compute(); | |
if (cur - prev1 >= WAIT) | |
{ | |
prev1 = cur; | |
//unsigned long _duration = duration; | |
//unsigned long _ticks = ticks; | |
//duration = 0; | |
//Calculate fan speed | |
// float Freq = (1e6 / float(_duration) * _ticks) / 2; | |
// speed = Freq * 60; | |
// ticks = 0; | |
//Turn the fans ON/OFF | |
if (round(duty) < DUTY_MIN) | |
{ | |
digitalWrite(RELAIS, HIGH); | |
PWM6 = 0; | |
fanRunning = false; | |
} | |
else | |
{ | |
fanRunning = true; | |
PWM6 = duty; | |
digitalWrite(RELAIS, LOW); | |
} | |
shouldPrint = true; /* Things have changed. remind to update the display */ | |
DEBUG("- Target; "); | |
DEBUG(storage.target); | |
DEBUG(" - Temp: "); | |
DEBUG(ctemp); | |
DEBUG(" - Duty: "); | |
DEBUG(map(round(duty), 0, 255, 0, 100)); | |
DEBUG(" - prev3: "); | |
DEBUG(prev3); | |
DEBUG("\n"); | |
} | |
/* Checks if the +/- buttons are pressed and if it's not the first time they've been pressed. */ | |
if (up && !lastUp == up && storage.target < 255) | |
{ | |
storage.target++; | |
} | |
if (down && !lastDown == down && storage.target > 0) | |
{ | |
storage.target--; | |
} | |
/* If either + or - buttons are pressed, enter target mode and display the current target on the lcd. */ | |
if (up || down) | |
{ | |
//targetMode = true; | |
shouldPrint = true; | |
prev3 = cur; | |
} | |
/* If 3 secs have elapsed and no button has been pressed, exit target mode. */ | |
if (cur - prev3 >= 3000) | |
{ | |
if (blink) | |
{ | |
blank = true; | |
blink = false; | |
shouldPrint = true; | |
} | |
else | |
{ | |
blank = false; | |
blink = true; | |
shouldPrint = true; | |
} | |
} | |
else | |
{ | |
saveConfig(); /* Save the config only when exiting targetMode to reduce EEPROM wear */ | |
} | |
if (shouldPrint) | |
{ | |
writeLCD(); | |
} | |
} | |
[/code] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment