maanantai 31. maaliskuuta 2014

Talouskellarin räppänän säädin

Ohjelmoitavat arduino piirit ovat viime aikoina olleet kiinnostukseni kohteena. Ledien vilkuttelun lisäksi piireillä saa tehtyä hyödyttäviäkin vempeleitä.

Kylmäkellarin lattian maalaamisen ja uusien hyllyjen tekemisen jälkeen päätin tehdä ulos menevään ilmanvaihtohormiin automaattisesti säätyvän venttiilin. Ajatus lähti siitä, että jos ulkona on kylmempi kuin kellarissa, niin kylmä ilma valuisi painovoimaisesti kellariin jäähdyttäen koko tilan. Jotta homma toimii kaikilla keleillä ja kellari ei mene vahingossa liian kylmäksi, portinvartijaksi tulee lämpötilaohjattu venttiili. 

Periaatekuva venttiilin ja antureiden sijainnista.

Homma alkoi varastossa olleen arduino pro micron ohjelman suunnittelulla. Osiksi valikoitui pro micron lisäksi maalaämpöpumpun sisätilaanturia varten ostamani 10kohm thermistorit ja RC-lennokista purettu normaali servo.

Softan pohjaksi löysin netistä muutamia hyviä sivuja arduinon käyttämisestä lämpömittarina. Vastuksen ohmien muuttaminen celsiuksiksi helpottaa huomattavasti venttiilin säätämistä. Koodista tuli loppupelissä kohtuullisen simppeli. En jaksanut alkaa siistimään ja optimoimaan sitä koska se toimi ihan nätisti noinkin. Tavoitelämpönä on 8 astetta ja säätö tapahtuu viiden sekunnin välein.



Varsinainen fyysinen venttiili on vielä tekemättä, mutta sehän on vain mekaanista työtä ;)

Koodi on päivitetty vastaamaan lopullista versiota, jossa mm. servon jännite on katkaistuna muutoin, kuin servon liikkuessa. 

Koodi:

#include <math.h>
#include <Servo.h>

#define NUMSAMPLES 5

Servo myservo;
int samples[NUMSAMPLES];
int pos;
int opttemp = 10;
int vaihtelu = 2;
const int ohjaus = 4;

void setup() {
 myservo.attach(9);
 pinMode (ohjaus, OUTPUT);
 Serial.begin(9600);
}

void loop() {
  
  uint8_t i;
  float average;

  // take N samples in a row, with a slight delay
  for (i=0; i< NUMSAMPLES; i++) {
   samples[i] = analogRead(A3);
   delay(10);
  }

  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
  }
  average /= NUMSAMPLES;

//  Serial.print("Analog reading: "); 
//  Serial.println(average);
  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = 10000 / average;
  
//  Serial.print("Vastus: ");
//  Serial.println(average);
  
  float steinhart;
  steinhart = average / 10000;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= 3950;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (25 + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
  
  int tempin;
  tempin = (int) steinhart;
  tempin = tempin * -1 + 49;
  int temp;
  
  Serial.print("Temp IN: ");
  Serial.println(tempin);
  
// ulkomittaus  
  uint8_t a;
  float average2;

  // take N samples in a row, with a slight delay
  for (a=0; a< NUMSAMPLES; a++) {
   samples[a] = analogRead(A2);
   delay(10);
  }

  // average all the samples out
  average = 0;
  for (a=0; a< NUMSAMPLES; a++) {
     average += samples[a];
  }
  average /= NUMSAMPLES;

//  Serial.print("Analog reading: "); 
//  Serial.println(average);
  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = 10000 / average;
  
//  Serial.print("Vastus: ");
//  Serial.println(average);
  
  float steinhart2;
  steinhart = average / 10000;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= 3950;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (25 + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
  
  int tempout;
  tempout = (int) steinhart;
  tempout = tempout * -1 + 49;
  int temp2;
  
  Serial.print("Temp OUT: ");
  Serial.println(tempout);
  
  if (tempin > opttemp & tempin > tempout & pos < 45) {    // jos sisälämpö > tavoite ja sisä on suurempi kuin ulko ja luukku on kiinni
       digitalWrite (ohjaus, HIGH);
       delay (100);
       for(pos == 0; pos < 90; pos += 1)                  // ajaa luukun auki 180 astetta 
       myservo.write(pos);
       delay(1500);
       digitalWrite (ohjaus, LOW);
       }
  if ((tempin < opttemp - vaihtelu | tempin < tempout) & pos > 45){    // jos sisä on < tavoite-vaihtelu tai sisä on pienempi kuin ulko ja luukku on auki
       digitalWrite (ohjaus, HIGH);
       delay (100);
       for(pos == 90; pos >=1; pos-=1)     // goes from 180 degrees to 0 degrees                   
       myservo.write(pos);              // tell servo to go to position in variable 'pos' 
       delay(1500);                          // waits 15ms for the servo to reach the position 
       digitalWrite (ohjaus, LOW);  
       }
  
Serial.println(pos);
  delay(1000);
}

Ei kommentteja:

Lähetä kommentti