Dziś może trochę mało życiowy przykład kończący opisy odczytów z czujników. Do Arduino mamy podpięte dwa czujniki: DHT22 mierzy temperaturę i wilgotność otoczenia, natomiast DS1820 przymocowany jest do zwierciadła teleskopu i mierzy jego temperaturę. Na podstawie odczytanych danych ustalana jest moc PWM dla sterowania dwóch urządzeń:
- grzałek eliminujących roszenie na optyce (na podstawie bieżącej wartości wilgotności względnej)
- wentylatora chłodzącego lustro (na podstawie różnicy temperatury pomiędzy otoczeniem i lustrem)
Kod jest dość prosty, bez obsługi LCD i portu szeregowego tym razem, żeby nie zaciemniać interesującej nas funkcjonalności. Moc grzejąca optykę obliczana jest w linijce
dewHeatPower = map(currentHum, 50, 100, 0, 100);
natomiast moc sterująca wentylatorem obliczana jest w ten prosty sposób:
fanPower = constrain(map(10*(currentTemp - currentDSTemp), 10, 50, 0, 100), 0, 100);
Timer odpowiada za cykliczne wywoływanie pomiaru przez oba czujniki i następnie na podstawie zmierzonych wartości obliczane są odpowiednie współczynniki wypełnienia PWM, które sterują odpowiednio mocą grzałki i obrotami wentylatora. Grzałkę i silnik oczywiście należy podpiąć przez tranzystor mocy jak pokazano przykładowo w poście nr. 5.
Oczywiście można znaleźć dużo bardzie zaawansowane biblioteki służące do sterowania ogrzewaniem i chłodzeniem na podstawie odczytanych danych i każdy może tutaj odpowiednią moc obliczać w dowolny sposób.
Cały kod wygląda tak:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <dht.h>
#include <Timer.h>
#define DHT22_PIN 2
#define DS8120_PIN 3
#define PWM_HEATER_PIN 5
#define PWM_FAN_PIN 6
OneWire oneWire(DS8120_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
dht DHT;
Timer timer;
boolean DS1820connected = false;
boolean DHT22connected = false;
float currentTemp; // bieżąca temperatura z czujnika DHT
float currentHum; // bieżąca wilgotność z czujnika DHT
float currentDewpoint; // obliczony punkt rosy na podstawie danych z czujnika DHT
float currentDSTemp; // bieżąca temperatura z czujnika DS przymocowanego do lustra
byte dewHeatPower = 0; // moc grzałki
byte fanPower = 0; // moc wentylatora
void setup() {
int chk = DHT.read22(DHT22_PIN);
if(chk == DHTLIB_OK) DHT22connected = true;
sensors.begin();
DS1820connected = sensors.getAddress(insideThermometer, 0);
if(DS1820connected) sensors.setResolution(insideThermometer, 10);
timer.every(1000, updateSensors);
}
void loop() {
timer.update();
}
void updateSensors() {
if (DS1820connected) {
sensors.requestTemperaturesByAddress(insideThermometer); // przy 10 bitowej dokładności trwa 188ms
currentDSTemp = sensors.getTempC(insideThermometer);
}
if (DHT22connected) {
DHT.read22(DHT22_PIN);
currentTemp = DHT.temperature;
currentHum = DHT.humidity;
currentDewpoint = dewPoint(currentTemp, currentHum);
dewHeatPower = map(currentHum, 50, 100, 0, 100);
}
if(DS1820connected && DHT22connected) fanPower = constrain(map(10*(currentTemp - currentDSTemp), 10, 50, 0, 100), 0, 100);
updatePWM();
}
void updatePWM() {
analogWrite(PWM_HEATER_PIN, map(dewHeatPower, 0, 100, 0, 255));
analogWrite(PWM_FAN_PIN, map(fanPower, 0, 100, 0, 255));
}
// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//
double dewPoint(double celsius, double humidity)
{
// (1) Saturation Vapor Pressure = ESGG(T)
double RATIO = 373.15 / (273.15 + celsius);
double RHS = -7.90298 * (RATIO - 1);
RHS += 5.02808 * log10(RATIO);
RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ;
RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
RHS += log10(1013.246);
// factor -3 is to adjust units - Vapor Pressure SVP * humidity
double VP = pow(10, RHS - 3) * humidity;
// (2) DEWPOINT = F(Vapor Pressure)
double T = log(VP/0.61078); // temp var
return (241.88 * T) / (17.558 - T);
}