Arduino UNO. Чергове оновлення функціоналу

При використанні душу на дачі за рік сталася біда – забились якісь труби. Відповідно напір води став менший, а проточний нагрівач все ще гріє сильно як і рік тому назад. Тому вода стає дуже гаряча, і всередині нагрівача спрацьовує запобіжник від перегріву. Він приблизно стпрацьовує при 48-50 градусах Цельсія.

Потім нагрів відключається і йде прохолодна вода – “літньої” температури. Через 30 секунд нагрів включається і все повторюється.

Щоб побороти дане неподобство я вирішив ввести новий функціонал в Arduino UNO – максимальну температуру нагріву. Для цього впаяв іще один світлодіод і 3 саморобні “кпопки”. При перевищенні допустимого максимуму ткмператури нагрів відключається, вмикається червоне світло. Кнопками можна виставити бажану максимальну температуру.

Ось що роблять кнопки

  1. Збільшити t на 1 градус
  2. Показати t на моніторі
  3. Зменшити 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 кВт навантаження спричинятиме поблимування їх неекономних лампочок.

Один коментар до “Arduino UNO. Чергове оновлення функціоналу”

  1. Якщо терморезистора немає, треба виводити помилку і не включати обігрів

Залишити відповідь до ОбновитиКод Скасувати відповідь

Ваша e-mail адреса не оприлюднюватиметься.

Я spam бот