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.
#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);
}