keskiviikko 4. tammikuuta 2017

”Kostutuskeskus”.

Tämä osio on SARJA-37:n viimeinen sovellus. Tässä on käytössä ja pääosassa ilman suhteellisen kosteuden ja lämpötilan anturi KY-015. Merkkivalona on kolmivärinen LED, missä on vilkutus sisäänrakennettuna (KY-034), Puhallinta ohjaa rele KY-019. Pääosassa on kosteus- ja lämpötila-anturi (KY-015). 
     Sarjaan-37 jää käsittelemättä joitakin moduuleita (reed-releitä, infrapuna lähetin/vastaanotin, kaltevuusanturi jne.), joille ehkä (ja toivottavasti) löytyy paikka jossain tulevissa pienissä kokeiluissa.
 
Tämä anturi (KY-015) perustuu elementtiin DHT11. Siitä löytyy netistä varsin paljon tietoa ja käyttöesimerkkejä. Useimmissa ohjelmaesimerkeissä on käytetty ohjelmakirjastoa #include <DHT11.h>. Se ei kuitenkaan kuulu Arduinon peruskirjastoon, enkä onnistunut lataamaan sitä mistään. Tämä puute johti siihen, että tämän kertainen ohjelma perustuu netistä otettuun esimerkkiin, mikä ei käytä tuota kirjastomoduulia. (Itse asiassa, kun tämä ohjelma oli jo valmis, sain lisättyä tuon kirjastotiedoston (DHT11.h) Aduino → libraries – hakemistoon, mutta työn takana oli!) Testaus jää toiseen kertaan.
     On myös hyvä huomata, että signaalipinni (Con_SarjaPinni = 8;), joka astetuksissa määritellään lähdöksi (OUTPUT), muutetaan pääohjelmassa välillä tuloksi ja välillä lähdöksi. Toisin sanoen tässä anturissa on ainoastaan yksi pinni, josta sekä käynnistetään että luetaan sarjamuotoista dataa.

DHT11 sarjasihnaali.
 
Ensimmäiseksi Arduino (MCU) lähettää käynnistyssignaalin. Pienen tauon jälkeen anturi (DHT) lähettää 40 bitin datan, mikä koostuu seuraavasti: kosteuden kokonaisosa (8bit), kosteuden desimaaliosa (8bit), lämpötilan kokonaisosa (8bit) sekä lämpötilan desimaaliosa (8bit). Näiden neljän perään vielä kahdeksanbittinen tarkistussumma, joka koostuu noiden neljän edellisen summasta.
Anturin ominaisuudet on ilmoitettu varsin selkeästi.


 Mitta-alueet ja tarkuus. Ne ovat aivan riittävät tähän tarkoitukseen. Netin esittelyistä käy myös selvästi ilmi, että anturi (DHT11) kalibroidaan tehtaalla valmiiksi noihin arvoin.
  
Moduuli KY-015 osoitti kyllä jotain aivan muuta. Se ilmoitti ilman kosteudeksi 20%. Se ei voinut pitää paikkaansa, sillä tuo kuivuus tuntuisi jo hengityksessä. Huoneessa oleva hiushydrometri osoitti 47%. Selvä ristiriita siis oli olemassa, mikä tietysti piti selvittää. Lämpötila näytti kyllä samaa toisen sisälämpömittarin kanssa. Myös desimaalit puuttuivat. Ne puuttuivat myös alkuperäisellä esimerkkiohjelmalla toteutettuna. Hylkäsin desimaalit, sillä noilla tarkkuuksilla niillä ei olisi suurtakaan merkitystä. 
 
Ensin piti selvittää todellinen huoneen suhteellinen kosteus. Mitä kuivempaa, sitä enemmän kosteus haihtuu. Tähän fysiikan lakiin perustuu perinteinen suhteellisen kosteuden mittaus. Mitataan kuivan anturin lämpötila ja märän anturin lämpötila. Koska haihtuminen vaatii energiaa, ei sitä ole saatavissa muulla tavoin kuin laskemalla lämpötilaa. Mittausjärjestely on viereisessä kuvassa.
 
Kuvassa on vesiastia (huoneenläpöistä vettä), puhallin ja kaksi lämpötila-anturia. Platina-100-anturit (Pt-100) ovat yleisempiä, mutta nämä ovat Nikkeli-100 (Ni-100), koska sellaisia sattui olemaan. Toinen anturi on peitetty sideharsolla, ja sen alahelma kostuu vedessä. Puhallin puhaltaa molempiin antureihin ilmaa, joten kuiva anturi on huoneen lämpötilainen ja märkä jäähtyy haihdutuksesta johtuen. Ohessa Ni-100 anturin vastusarvot huoneen lämpötilan ympäristössä:
Vastusmuutos näillä antureilla on niin pieni, että ilman vahvistimia niitä on hankala kytkeä Arduinoon, mutta vastus on helppo mitata yleismittarilla sekä katsoa lämpötiloja vastaavat arvot taulukosta. Saatujen arvojen muuttaminen suhteelliseksi kosteudeksi onnistuu käyrästön avulla:


Tuota käyrästöä piti pienentää niin pajon,. Että sen käyttö lienee hankalaa tällä sivulla, mutta seuraavasta osoitteesta se on käytettävissä kokonaisena:
 
Kuiva anturi oli 112,9ohm, vastaten 22,7ºC ja märkä anturi 108,4ohm, vastaten 15,1ºC. Tällä lämpötilaerolla huoneen suhteellinen kosteus on siis noin 45%.
      En tiedä, johtuiko anturin (KY-015) laadusta vai mistä, mutta se tietysti näytti, kuten mainitsin, aivan väärin. Siksi ohjelmassa on anturista saatuun arvoon lisäys, jolloin lukema näytössä on kuta kuinkin oikein. Ihmiselle suositeltava suhteellinen kosteus liikkuu siellä 35 ja 60%:in välillä. Anturin signaali kyllä muuttui kosteuden muuttuessa. Ilmeisesti vain pohja-arvo oli kalibroimatta tehtaalla?


Tuossa vailla kostutusosaa ja seuraavassa kuvassa kostutuksen kanssa.
 
Puhallin puhaltaa ilmaa märän "vanun" läpi anturille.
  
Ohjelmassa ohjataan kosteusanturin lisäksi relettä ja LEDiä. Releyksikkö (KY-019) ja vilkulla varustettua LEDi- (KY-034) ohjataan yksinkertaisella ON-OFF-säädöllä. Kun kosteus laskee tietyn rajan alle, puhallin käynnistyy ja LEDi alkaa vilkkua. Kun ylempi raja ylittyy, pysähtyy ohjaus ja ohjelma alkaa odottaa kosteustiedon alenemista. Tämä toistuu automaattisesti. Videosta (antinarduvideo32.youtube.com) saa jonkinlaisen käsityksen toiminnasta. Se ei kuitenkaan ole kestoltaan niin pitkä, että siinä näkyisi kostutus- ja odotusvaiheet.
  
Kevät ja pakkaset ovat tulossa. Huoneiden sisäilman sopivan kosteuden ylläpitämiseksi tarvitaan toki huomattavasti tehokkaampi kostutin kuin tämä. Hyviä pakkaspäiviä!
 
OHJELMA 32
/***************************************
* Ohjelma 32
* 4.1.2017
* KOSTUTUSKESKUS
**************************************/

// MÄÄRITTELYT:
// LCD-näyttö
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4,3,2);
const byteapi = B11100001; // ä
const byte opi = B11101111; // ö
const byte ast = B11011111; // aste

// Perusmäärityksiä
const int Con_SarjaPinni = 8;
const int Con_Rele = 6;
const int Con_LEDPinni = 7;
byte int _data [5];

// ALIOHJELMAT
// Datan luku
byte Fun_LueData () {
byte data;
    for (int i = 0; i < 8; i ++) {
      if (digitalRead (Con_SarjaPinni) == false) {
         while (digitalRead (Con_SarjaPinni) == false); // Odotus, kun 0 (false)
            delayMicroseconds (30); // Odotetaan keskelle pulssia
             if (digitalRead (Con_SarjaPinni) == true)
         data |= (1 << (7-i)); // Jos erisuuri, bittisiirto vasemmalle
      while (digitalRead (Con_SarjaPinni) == true); // Jos 1 (true), odottaa seuraavaa bittiä
}
}
return data; // Palautettava arvo
} // Luennan loppu

// Anturin ohjaus ja luenta
void Fun_SarjaIO() {
    digitalWrite (Con_SarjaPinni, false); // Käynnistyssignaali
    delay (30); // Viive pidempi kuin 18ms,DHT11 tunnistaa käynnistyksen
    digitalWrite (Con_SarjaPinni, true);
    delayMicroseconds(40); // Odotetaan vastausta
    pinMode (Con_SarjaPinni, INPUT); // Asetetaan tuloksi
    while (digitalRead (Con_SarjaPinni) == true);
       delayMicroseconds(80); // DHT11 vastaus 80us aikana
       if (digitalRead (Con_SarjaPinni) == false);
         delayMicroseconds(80);
// Vastaanotetaan lämpötila ja kosteusdata. Tarkistusbittiä ei huomioida.
    for (int i = 0; i < 4; i ++)
      Byt_data[i] = Fun_LueData ();
      pinMode (Con_SarjaPinni, OUTPUT); // Asetetaan lähdöksi
          digitalWrite (Con_SarjaPinni, true); // Vapautusbitti seuraavaa luentaa varten
}// Ohjausfunktio loppu

// ASETUKSET:
void setup(){
    Serial.begin(9600);
    lcd.begin(20,2);
    lcd.clear();
// Tekstit näyttöön, suoritetaan kerran
    lcd.setCursor(0, 0);
    lcd.print("Suht.kosteus: %");
    lcd.setCursor(0, 1);
    lcd.print(" L");
    lcd.write(api);
    lcd.print("mp");
    lcd.write(opi);
    lcd.print("tila: ");
    lcd.write(ast);
    lcd.print("C");
// IO-pinnien määrittely
    pinMode(Con_SarjaPinni, OUTPUT);
    pinMode(Con_LEDPinni, OUTPUT);
    pinMode(Con_Rele, OUTPUT);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
    Fun_SarjaIO ();
        lcd.setCursor(14, 0);
        lcd.print(Byt_data [0]+23, DEC);
// lcd.print(".");
// lcd.print(Byt_data [1], DEC);
        lcd.setCursor(14, 1);
        lcd.print(Byt_data [2], DEC);
// lcd.print(".");
// lcd.print(Byt_data [3], DEC);
        if(Byt_data [0] + 15 < 40){
           digitalWrite (Con_LEDPinni, HIGH);
           digitalWrite (Con_Rele, HIGH);
        }else if(Byt_data [0] + 23 > 47) {
           digitalWrite (Con_LEDPinni, LOW);
           digitalWrite (Con_Rele, LOW);
}// ohjaus loppu

delay(1000);
} // Pääohjelma LOPPU
 

Ei kommentteja:

Lähetä kommentti