Slimme Kelder Ventilatiesysteem: Arduino-gestuurde Vochtcontrole
Onderdelen en benodigdheden
| Arduino Nano R3 | Aantal: 1 |
| IO Expander | Aantal: 1 |
| IO Expander Bundle | Aantal: 1 |
Apps en online diensten
| Arduino IDE |
Over dit project
Functielijst
- Binnen/buiten temperatuur- en vochtigheidssensoren
- Slimme ventilatorbesturing op basis van vochtvergelijking
- Vocht in kelder/kruipruimte reduceren
- Helpt schimmelvorming te voorkomen
- Slim ventileren bespaart stroom

Benodigde onderdelen voor het ventilatiesysteem
- IO Expander
- 1-Wire naar I2C converter
- Arduino Nano
- 1-kanaals 5V DC relais
- 2× SHT10 vochtigheidssensor
- I2C SSD1306 OLED 128×64 display
- 2× 110V 172×150×38mm 0,34A 2400 RPM kogellager ventilatoren
- 158×90×65mm waterdichte plastic behuizing (IP68)
- IP68 PG7 & PG9 waterdichte nylon kabelklemmen
- 2× RJ11 keystone schroefklemmen
- 2× Keystone behuizing
- 2× 50ft 4C4P RJ11 draad
- 6" 4C4P RJ11 draad
- 100ft 110V draad
- AC-stekker
- 2,54mm header draad
- 12VDC 1A wandadapter voeding
Bedradingsschema

OLED-display

Waarom de IO Expander?
- Simpeler ontwerp
- Kant-en-klare onderdelen
- Geen 1-Wire driver nodig
- Geen relais-driver nodig
- Geen OLED-display driver nodig
- Geen display-fonts die Arduino-geheugen innemen
- Geen vochtigheidssensor-driver nodig
- Bespaart code-ruimte: slechts 6106 bytes (19%)
- Code in minder dan een dag geschreven
- Makkelijk te bedraden met standaard RJ11-telefoonkabel
- Geen sensor-kabellengte problemen
- Goedkoper dan commerciële systemen
- Eenvoudig aan te passen aan individuele eisen
- Enkele voeding
Het systeem bouwen
- Verbind de Arduino Nano met de IO Expander en programmeer het met de onderstaande code. De 6-pins header is de software-seriële debug-poort en niet nodig in de definitieve installatie.

- Zorg dat je het
ONEWIRE_TO_I2C_ROMadres aanpast aan je 1-Wire naar I2C-adres.
Code (Basement/Crawlspace Ventilation System v1.1)
/* IO Expander
* Basement/Crawlspace Ventilation System v1.1
*/
#include <math.h>
#include <SoftwareSerial.h>
#include <avr/wdt.h>
#include "IOExpander.h"
#define FAHRENHEIT
#define ONEWIRE_TO_I2C_ROM "i4s71"
#define INIT_OLED "st13;si;sc;sd"
#define HUMIDITY_SENSOR_INSIDE "s6t1"
#define HUMIDITY_SENSOR_OUTSIDE "s8t1"
#define FAN_ON "r1o"
#define FAN_OFF "r1f"
#define ABSOLUTE_DELTA_FAN_ON 1 // Ventilator aan als absolute vochtigheid binnen >= buiten
#define ABSOLUTE_DELTA_FAN_OFF 0.5 // Ventilator uit als absolute vochtigheid binnen <= buiten
#define OUTSIDE_RELATIVE_FAN_ON 88 // Ventilator aan als buiten relatieve vochtigheid <= %
#define OUTSIDE_RELATIVE_FAN_OFF 90 // Ventilator uit als buiten relatieve vochtigheid >= %
#define MINIMUM_TEMPERATURE 15 // Cyclisch aan/uit als buiten temp <= 15°C/59°F
#define FAN_ON_TIME (20*60*1000L) // 20 min
#define FAN_OFF_TIME (20*60*1000L) // 20 min
//#define SERIAL_DEBUG
#define SERIAL_TIMEOUT 5000
#ifdef SERIAL_DEBUG
SoftwareSerial swSerial(8,7);
#endif
struct HS {
float temp;
float relative;
float absolute;
bool error;
};
int led = 13;
bool init_oled = true;
long ontime, offtime;
#ifdef FAHRENHEIT
#define C2F(temp) CelsiusToFahrenheit(temp)
float CelsiusToFahrenheit(float celsius) {
return ((celsius*9)/5)+32;
}
#else
#define C2F(temp) (temp)
#endif
void SerialPrint(const char* str, float decimal, char error) {
Serial.print(str);
if (error) Serial.print(F("NA"));
else Serial.print(decimal, 1);
}
float DewPoint(float temp, float humidity) {
float t = (17.625 * temp) / (243.04 + temp);
float l = log(humidity/100);
float b = l + t;
return (243.04*b)/(17.625-b); // August-Roche-Magnus
}
#define MOLAR_MASS_OF_WATER 18.01534
#define UNIVERSAL_GAS_CONSTANT 8.21447215
float AbsoluteHumidity(float temp, float relative) {
// Bron: carnotcycle.wordpress.com - Buck (1981) formule
return (6.1121 * pow(2.718281828, (17.67 * temp) / (temp + 243.5)) * relative * MOLAR_MASS_OF_WATER) / ((273.15 + temp) * UNIVERSAL_GAS_CONSTANT);
}
void ReadHumiditySensor(HS* hs) {
SerialCmd("sr");
if (SerialReadFloat(&hs->temp) && SerialReadFloat(&hs->relative)) {
hs->absolute = AbsoluteHumidity(hs->temp, hs->relative);
hs->error = false;
} else hs->error = true;
SerialReadUntilDone();
}
void setup() {
Serial.begin(115200);
#ifdef SERIAL_DEBUG
swSerial.begin(115200);
#endif
pinMode(led, OUTPUT);
wdt_enable(WDTO_8S); // Watchdog timer 8 seconden
offtime = millis() - FAN_OFF_TIME;
}
void loop() {
HS inside, outside;
static bool fan = false;
static bool cycle = false;
static long last_time = -(60L * 1000L);
Serial.println();
if (SerialReadUntilDone()) {
// Sensoren max 1x per minuut uitlezen (anders zelfverhitting)
if (millis() - last_time > 60L * 1000L) {
if (SerialCmdDone(HUMIDITY_SENSOR_INSIDE)) ReadHumiditySensor(&inside);
if (SerialCmdDone(HUMIDITY_SENSOR_OUTSIDE)) ReadHumiditySensor(&outside);
if (inside.error || outside.error) fan = false;
else {
if (fan) { // Ventilator draait
if (outside.relative >= OUTSIDE_RELATIVE_FAN_OFF || inside.absolute - outside.absolute <= ABSOLUTE_DELTA_FAN_OFF)
cycle = fan = false;
else {
if (cycle && outside.temp <= MINIMUM_TEMPERATURE && millis() - ontime > FAN_ON_TIME)
fan = false;
}
if (!fan) offtime = millis();
} else { // Ventilator uit
if (outside.relative <= OUTSIDE_RELATIVE_FAN_ON && inside.absolute - outside.absolute >= ABSOLUTE_DELTA_FAN_ON)
cycle = fan = true;
if (cycle && outside.temp <= MINIMUM_TEMPERATURE)
fan = (millis() - offtime > FAN_OFF_TIME) ? true : false;
if (fan) ontime = millis();
}
}
if (fan) SerialCmdDone(FAN_ON);
else SerialCmdDone(FAN_OFF);
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM)) {
if (init_oled) {
SerialCmdDone(INIT_OLED);
init_oled = false;
}
// Display updaten met binnen/buiten waarden en ventilatorstatus
SerialCmdDone("st13;sc;sf0;sa1;sd70,0,\"INSIDE\";sd127,0,\"OUTSIDE\";sf1;sa0;sd0,12,248,\""
#ifdef FAHRENHEIT
"F"
#else
"C"
#endif
"\";sd0,30,\"%\",sf0;sd0,50,\"g/m\";sd20,46,\"3\";");
SerialPrint("sf1;sa1;sd70,12,\"\"", C2F(inside.temp), inside.error);
SerialPrint("\";sd70,30,\"\"", inside.relative, inside.error);
SerialPrint("\";sd70,48,\"\"", inside.absolute, inside.error);
SerialPrint("\";sd127,12,\"\"", C2F(outside.temp), outside.error);
SerialPrint("\";sd127,30,\"\"", outside.relative, outside.error);
SerialPrint("\";sd127,48,\"\"", outside.absolute, outside.error);
Serial.print("\";");
Serial.print("sf0;sa0;sd0,0,\"\"");
if (fan) Serial.print("FAN");
else Serial.print("v1.1");
Serial.println("\";sd");
SerialReadUntilDone();
} else init_oled = true;
last_time = millis();
}
delay(1000);
} else {
// Communicatiefout: LED knipperen
digitalWrite(led, HIGH); delay(500);
digitalWrite(led, LOW); delay(500);
init_oled = true;
}
wdt_reset();
}
Let op: Als je de Arduino Nano programmeert via USB, moet je het loskoppelen van de IO Expander (deelt dezelfde seriële poort). Voor debugging: programmeer via ICSP-poort en uncomment SERIAL_DEBUG.
- Sluit de 110VAC-draad aan op beide ventilatoren.

- Boor een 7/16" en 9/16" gat in de behuizing voor PG7 en PG9 klemmen. Gebruik een Dremel om de gaten iets te vergroten tot de klemmen strak zitten. PG7 voor 12VDC invoer, PG9 voor sensoren en ventilatoren.

- Zoek een open, niet geblokkeerd luchtgat – dit wordt de uitlaat. Zorg dat alle andere gaten aan de overkant open zijn (luchtinlaat). Sluit aangrenzende gaten om een regionale (niet lokale) luchtstroom te creëren.

- Monteer de ventilatoren aan de binnenkant van het luchtgat met kabelbinders. Controleer de blasrichting (naar buiten).

- Vind een bestaande toegang en voer de buiten-sensor-draad naar binnen. Plaats de sensor ver genoeg van het huis/obstructies voor correcte omgevingsmeting. Controleer met lokale weersrapporten.

- Sluit buiten-sensor aan op keystone jack/behuizing en monteer binnen.

- Sluit binnen-sensor aan (centrale locatie of vochtige plek) en monteer.

- Verbind 50ft RJ11-draden met sensoren en voer samen met ventilatordraad naar toegangspunt voor besturingsbehuizing.

- Sluit alle draden aan, monteer alles in de besturingsbehuizing (dubbelzijdig tape, schuim). Test het systeem: los Arduino van IO Expander, verbind met PC voor handmatige relais/ventilatorcontrole. Na verificatie: alles in behuizing en geniet van je slimme vochtcontrole!

Update 20-3-2019
Na enkele maanden draaien in mijn kruipruimte (0 crashes, piek vochtigheid >95% na lekkage CV-ketel) is de relatieve vochtigheid gedaald tot <50%. Het systeem werkt continu en betrouwbaar!

OLED-display gewijzigd van SSD1306 0,96" naar SH1106 1,3" – veel beter leesbaar. Wijziging was eenvoudig met IO Expander firmware-update: ST10 → ST13 in code.

Update 12-9-2019
Versie v1.1 uitgegeven: koude-start probleem opgelost waar OLED leeg bleef. Systeem ventileert nog steeds mijn kruipruimte!
Schema

Productieproces
- Betrouwbaar Arduino RFID Aanwezigheidssysteem Aangedreven door Python
- Arduino Uno Gebaseerde Mensendetectie Robot: Stap-voor-stap Sensorintegratie
- Bluetooth-gecontroleerde Arduino Spybot bouwen
- FlickMote: Gebarengecontroleerde IR-afstandsbediening voor Slimme Huizen
- DIY Arduino TV-B-Gone: Universele TV-uit-schakelaar
- Bouw een Aangepaste LED Hoofdklok met Alarm – Zichtbaar vanaf 12 Meter
- SERENA: Een Aangepast Arduino Mega 2560 Alarmsysteem Met TFT LCD Touchscreen
- Arduino-gestuurd automatische plantenwateringssysteem
- Real-time Bosbrandbewakingssysteem met SMS-alarmen
- Real-time RFID aanwezigheidssysteem met Arduino en Google Sheets
- Ventilatiesystemen Begrijpen: Uw Binnenlucht Vers en Gezond Houden