При використанні душу на дачі за рік сталася біда – забились якісь труби. Відповідно напір води став менший, а проточний нагрівач все ще гріє сильно як і рік тому назад. Тому вода стає дуже гаряча, і всередині нагрівача спрацьовує запобіжник від перегріву. Він приблизно стпрацьовує при 48-50 градусах Цельсія.
Потім нагрів відключається і йде прохолодна вода – “літньої” температури. Через 30 секунд нагрів включається і все повторюється.
Щоб побороти дане неподобство я вирішив ввести новий функціонал в Arduino UNO – максимальну температуру нагріву. Для цього впаяв іще один світлодіод і 3 саморобні “кпопки”. При перевищенні допустимого максимуму ткмператури нагрів відключається, вмикається червоне світло. Кнопками можна виставити бажану максимальну температуру.
Ось що роблять кнопки
- Збільшити t на 1 градус
- Показати t на моніторі
- Зменшити t на 1 градус
Максимальна температура зберігається в енергонезалежній пам’яті EEPROM. Тобто виставлена температура збережеться і після відключення всіх приладів. Щож, публікую код:
#include <EEPROM.h>
#define SERIAL_R 49000 // сопротивление последовательного резистора, 49 кОм
#define B 3950 // B-коэффициент
#define THERMISTOR_R 50000 // номинальное сопротивления термистора, 50 кОм
#define NOMINAL_T 25 // номинальная температура (при которой TR = 100 кОм)
#define MANUAL_CORRECTION 0 // РУЧНА КОРЕКЦІЯ температури на виході
const byte tempPin = A0;
int waterFlowNormal, minimumWaterFlow, TC2_OVF;
int afterReset = 0;
int heatOff = 7;
int heatOn = 4;
int transistor = 8;
int overHeat = 9;
int readVal;
bool settingsMaxTempMode = false;
int currentTemperature;
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
pinMode(7, OUTPUT);
pinMode(4, OUTPUT);
pinMode(2, OUTPUT);
pinMode(overHeat, OUTPUT);
pinMode(transistor, OUTPUT);
pinMode(5, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
// set EEPROM cell for first time, or make it normal value
byte val;
val = EEPROM[0];
if (val > 80) {
EEPROM[0] = 43;
}
if (val < 10) {
EEPROM[0] = 43;
}
// timer2 setup from https://www.teachmemicro.com/arduino-timer-interrupt-tutorial/
TIMSK2 = (TIMSK2 & B11111110) | 0x01;
TCCR2B = (TCCR2B & B11111000) | 0x07;
// Timer/Counter 1 initialization
// Clock source: T1 pin Rising Edge
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: On
// Input Capture on Rising Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0) | (0 << WGM11) | (0 << WGM10);
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (0 << WGM13) | (0 << WGM12) | (1 << CS12) | (1 << CS11) | (1 << CS10);
TCNT1H = 0x00;
TCNT1L = 0x00;
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x00;
OCR1AL = 0x00;
OCR1BH = 0x00;
OCR1BL = 0x00;
minimumWaterFlow = 1;
Serial.begin( 9600 );
pinMode( tempPin, INPUT );
}
ISR(TIMER2_OVF_vect) {
TC2_OVF++;
if (TC2_OVF > 30) { // 30 is 10 LED togles in 19 seconds
TC2_OVF = 0;
// Toggle LED
digitalWrite( 2, digitalRead( 2 ) ^ 1 );
// now thermistor logic
int t = analogRead( tempPin );
float tr = 1023.0 / t - 1;
tr = SERIAL_R / tr;
float steinhart;
steinhart = tr / THERMISTOR_R; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= B; // 1/B * ln(R/Ro)
steinhart += 1.0 / (NOMINAL_T + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15;
int rxresult = (int)steinhart + MANUAL_CORRECTION;
currentTemperature = rxresult;
if (settingsMaxTempMode) {
byte val;
val = EEPROM[0];
Serial.println(val);
} else {
if (rxresult < -22) {
Serial.println("ER");
} else {
Serial.println(rxresult);
}
}
if (afterReset < 100) {
afterReset++;
}
//code for timer counting impulses
if ( TIFR1 & (1 << TOV1 )) { // if it has been overflow
waterFlowNormal = 1; // because overflow means in was more than 65535 tics (real test leads from ~5 to ~30)
TIFR1 = (1 << TOV1 ); // clear the flag of overflow
}
else {
if ((short int)TCNT1 > minimumWaterFlow) {
waterFlowNormal = 1;
}
else {
waterFlowNormal = 0;
}
}
TCNT1 = 0; // clear in any case
}
}
void loop() {
if (afterReset < 6) {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(70);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(60);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
byte maxTemperature = EEPROM[0];
if ((waterFlowNormal == 1) and (currentTemperature <= maxTemperature)) {
digitalWrite(heatOff, LOW);
digitalWrite(heatOn, HIGH);
digitalWrite(transistor, HIGH);
}
else {
digitalWrite(heatOff, HIGH);
digitalWrite(heatOn, LOW);
digitalWrite(transistor, LOW);
}
if (currentTemperature > maxTemperature) {
digitalWrite(overHeat, true);
} else {
digitalWrite(overHeat, false);
}
// Button Set Max Temp Minus 1
readVal = digitalRead(10);
if (readVal) {
digitalWrite(overHeat, false);
}
else {
// button pressed
digitalWrite(overHeat, true);
byte val;
val = EEPROM[0];
EEPROM[0] = val - 1;
delay(400);
}
// Button Set Max Temp Plus 1
readVal = digitalRead(12);
if (readVal) {
digitalWrite(overHeat, false);
}
else {
// button pressed
digitalWrite(overHeat, true);
byte val;
val = EEPROM[0];
EEPROM[0] = val + 1;
delay(400);
}
// Button Read Max Temp To UART
readVal = digitalRead(11);
if (readVal) {
digitalWrite(overHeat, false);
settingsMaxTempMode = false;
}
else {
// button pressed
digitalWrite(overHeat, true);
settingsMaxTempMode = true;
delay(400);
}
}
Тести проводив “програмно”, так як код пишу в м. Полтава, а сама установка нагріву і душ знаходяться в будинку в селі Черкасівка. Надіюсь що я не помилився і зможу приймати душ, хоч із зменшеним напором води, але із стабільною температурою (реле буде швидко клацати і підтримувати температуру в межах +/- 1 C). До того ж – це економія електроенергії – зменшений потік води, нагрів включається і виключається. Сусідам не позаздриш – так як 5.5 кВт навантаження спричинятиме поблимування їх неекономних лампочок.