Omega B - Kombi - Projekt "Sonnenstandsabhängige Standlüftung"
Hallo Zusammen,
mir kam neulich spontan der Einfall, als ich hinten am E-Satz der AHK gewerkelt habe(anders Thema, Nervkram mit nachgerüstetem Westfalia-Mist), ob man nicht die Zwangsentlüftung auch als BElüftung an heißen Tagen nutzen könnte.
Bei ein paar Herstellern gab es früher mal (oder heute noch?) die Option, sich im Schiebedach eine Solarzelle mitzubestellen, die bei entsprechend heißen Tagen den Ventilator im Stand auf niedriger Stufe laufen lässt.
Zitat:
HINWEIS:
Mir ist bewusst, dass das hier eher in die Kategorie "Hobbybastelei" geht als in die Richtung "Praktischer Nutzen" 🙂
Von der Größe her würde sogar ziemlich gut ein 120x120mm PC-Lüfter an eine der beiden Entlüftungsmembranen passen. Strom könnte man sich vom AHK-Stecker abgreifen (falls man keine AHK hat, muss vorne noch eine Sicherung gesteckt werden, dann hat man Dauerplus an der Buchse). Aktivieren könnte man den Lüfter über eine einfache Schaltung mit einer Photodiode, die ab einer bestimmten Einstrahlleistung ein Relais öffnet. Soweit die Theorie.
Luftmenge:
Der Lüfter hat eine Kubikleistung von 70m3 pro Stunde. Das wird er nicht erreichen, da ja baulich ein paar Hinternisse (Lüftungskanäle, Entlüftungsmembran etc.) zu überwinden sind. Wenn wir allerdings nur die Hälfte des Luftstroms als Berechnungsgrundlage nehmen, würden wir immerhin fast 4x pro Stunde das Luftvolumen im Omega austauschen, was die Stauhitze merklich reduzieren sollte.
Stromverbrauch:
Der Lüfter braucht 0,5 A bei 12 V. Man kann ihn also eine Weile laufen lassen, bis die Batterie kritisch belastet wird. Ein Batteriewächter wäre evtl. sinnvoll.
Bauliche Maßnahmen:
Ich habe noch keine Idee, wie man den Lüfter befestigen kann. Das sollte aber machbar sein. Außerdem müsste man noch ein paar Löcher in die Reserveradabdeckung bohren, um den Luftstrom zu erhöhen. Aktuell sieht es so aus, als ob die Mulde durch die Abdeckung recht dicht abgeschlossen wird. Außerdem müsste noch die Schaltelektronik irgendwo an der Heck-Seitenscheibe untergebracht werden. Die Gefahr des "Belüftungskurzschlusses", also der Ansaugung der Frischluft direkt durch die andere Zwangsentlüftung statt durch das Fahrzeug, ist gering, da die Membran den Luftstrom nur in eine Richtung durchlässt.
Warum nicht einfach ein Fenster auflassen?!
Zugegeben, das scheint sinnvoller zu sein. Ist es auch, bringt aber ein paar Nachteile. Erstens fliegt bei uns gerade furchtbar viel Blütenstaub, der würde durch die Lüfterkonstruktion im Innenraumfilter hängen bleiben. Zweitens kann man nicht immer überall ein Fenster offen lassen und drittens ist so auch mal ein kleiner Schauer verkraftbar. Außerdem ist das doch viel cooler so 🙂
Ich habe gerade mal ein Thermometer ins Auto gestellt und den Lüfter angeworfen. Mal sehn, ob sich etwas verändert. Falls nicht, wars eine nette Idee - falls doch, muss ich mich mal in Schaltungsaufbau einlesen 😉
Anbei noch ein Bild, natürlich nur provisorisch.
Wünsche euch einen schönen Sonntag! Hier in Bayern scheint die Sonne und es ist schön warm 🙂
Beste Antwort im Thema
Die Ansteuerung der ECC wäre mit einem Arduino problemlos möglich.
Eingänge: NTC und ein entsprechender Lux-Sensor?
Wenn der Omega mit ECC so nen Igel hat, dann legen vermutlich verschiedene Spannungspegel die Lüfterdrehzahl fest.
Grüße
92 Antworten
Aktueller Stand:
Er misst und schaltet 🙂 Momentan mangels Hardware nur die LED.
Wie das ganze in Live aussieht sieht man hier.
Es erscheint außerdem noch ein Symbol im Display.
Aktuell ist der Schwellenwert für die Aktivierung bei >27°, ein Fantasiewert.
Der Code ist bis jetzt bei ca. 200 Zeilen, hier ist aber noch viel Datenmüll und ein paar unschöne Dinge drin.
Allerdings sind ja noch viele Funktionen garnicht integriert, da ich die entsprechenden Sensoren und Schaltkreise noch nicht habe. Er wird also weiter wachsen.
Am zeitraubendsten war heute tatsächlich was absolut banals: das drehende Symbol soll den Ventilatorbetrieb symbolisieren. Da Arduino aber keine Vektorlinien sondern Pixellinien zeichnet, musste ich erstmal wieder gaaaaaaaanz tief in meinem Gehirn nach angestaubten Mathekenntnissen wühlen (Stichwort Drehmatrize🙄) um die Gerade, die durch vier Pixelpunkte definiert wird, um ein Drehzentrum zu drehen. Ist noch nicht fertig, gefällt mir noch nicht.
Das sieht dann im Code später so aus:
Code:
AventwingXi = ventcircleX + (ventwingX1 - ventcircleX) *
cos(rotation) - (ventwingY1 - ventcircleY) * sin(rotation);
AventwingYi = ventcircleY + (ventwingX1 - ventcircleX) +
sin(rotation) + (ventwingY1 - ventcircleY) * cos(rotation);
AventwingX2i = ventwingX2 - ((ventcircleX + (ventwingX2 -
ventcircleX) * cos(-rotation) - (ventwingY2 - ventcircleY) *
sin(-rotation)) - ventwingX2);
AventwingY2i = ventcircleY + (ventwingX2 - ventcircleX) +
sin(-rotation) + (ventwingY2 - ventcircleY) * cos(-rotation);
display.drawLine(AventwingXi, AventwingYi, AventwingX2i, AventwingY2i, WHITE);
Bitte keine Kommentare zu meinen kryptischen Variablennamen 😉
Für Mathematiker, hier die Formel für die x-Koordinate:
Code:
x' = x0 + (x - x0) * cos(phi) - (y - y0) * sin(phi)
Vieles ist aber so noch nicht umsetzbar. z.B. braucht der Arduino später auf alle Fälle ein Kl 15-Signal, damit er im Fahrbetrieb die Lüftungsfunktion einstellt. Ich weiß nämlich nicht, wie die Klima reagiert, wenn sie während der Fahrt auf einmal ein Standheizungs-Signal erhält 🙂 Wäre schön, wenn der Fahrbetrieb hierarchisch höherwertig wäre, aber da mangelt es mir an Wissen.
Außerdem will ich ja noch weiter Sensoren auslesen/ausgeben lassen, die ich an verschiedenen Stellen im Motorraum anbringen will - einfach interessehalber. Näheres dazu gibts hier:
Einschaltemperaturen Motorlüfter auf den Seiten weiter hinten.
Vom Radio würde ich auch gerne das "Licht an"-Signal abgreifen, um das OLED-Display zu dimmen (das ist überraschend hell).
Und und und.... 🙂
Wenn man erstmal anfängt, wirds zum Gigaprojekt.
Schau mal in die UTFT- Library bzw. bei Henning Karlsen auf der Homepage- da gibt es einen Sketch für eine Analoguhr... das könnte dir eine Lösung für ein drehendes Symbol zeigen...
Kurzer aktueller Stand 🙂
Es treffen immer mehr Teile ein und die Funktion (und der Code) wächst und wächst 🙂
Anbei mal ein Bild. Man sieht, dass mir gerade die Kabel ausgegangen sind, also läuft er momentan nicht. Das hängt aber nur daran, dass ich heute den SD-Reader anschließen wollte. Tatsächlich kann er schon was, aber natürlich fehlt noch etwa die Hälfte der Peripherie.
Hier auch mal ein Auszug des Codes, noch fehlerhaft (weil ichs gerade nicht testen kann).
Code:
////////////////////////////////////////////////////// SENSOREN
#include <Wire.h>
#include "DHT.h"
#define DHTPIN 2 // what digital pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);
// Lux-Sensor-Adresse
const byte BH1750FVI_I2CADDRESS = 0x23; // I2C address (ADD=L=0100011)
////////////////////////////////////////////////////// DISPLAY
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
////////////////////////////////////////////////////// VARIABLEN
int i; // Durchlauf-Counter
const int Tempschwelle = 25; // Temperaturschwelle, ab dem die Ventilation einsetzt
const int Luxschwelle = 1000; // Einstrahlungslevel, ab dem die Ventilation einsetzt
// Display-Abmessungen
int dspH = display.height();
int dspW = display.width();
// Lux-Werte
byte luxBuffer[2];
// TempHmdty
int t1, h1, hic1;
// Array
int ArrayStore, TempMax, TempMin;
int arrNr = dspW - 20;
int TempArray[108];
int HmdtyArray[108];
// cc = CoolingCounter
int cc;
// Textformatierung
int bigtext = 5;
// Geschwindigkeit des Programms
int velocity = 2000;
void setup() {
Wire.begin(); //Lichtsensor
Serial.begin(9600);
// SENSOREN
dht.begin();
pinMode(13, OUTPUT); // on-board LED
// pinMode(2, INPUT_PULLUP); // Sensor ohne Pull-Up auslesen
LuxInit(BH1750FVI_I2CADDRESS);
delay(1); // For safety reason, to settle the mode
// DISPLAY
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
}
void loop() {
delay(velocity);
////////// TEMP/HMDTY-WERTE AUSLESEN
t1 = TempHmdty();
h1 = TempHmdty();
hic1 = TempHmdty();
////////// LUX-WERTE AUSLESEN
unsigned int luxValue = 0; // Max. sensorValue allowed up to (2^16)-1
if (LuxRead(BH1750FVI_I2CADDRESS) == 2)
{
luxValue = ((luxBuffer[0] { 8) | luxBuffer[1]); // Combine 2 bytes
}
////////// ARRAY AUFBAUEN
Array(t1, h1);
////////// WERTE ANZEIGEN
DisplayValuesInside(t1, h1, hic1, luxValue);
////////// SERIELLE AUSGABE
SerialPrint(t1, h1, hic1, luxValue);
////////// COOLING
if (t1 > Tempschwelle || luxValue > Luxschwelle) {
cc++;
}
if (cc >= 60 / (velocity / 1000)) {
CoolingSymbol();
CoolingStart();
cc = 0;
}
////////// GRAPH
if (i == 10) {
Graph(TempMin, TempMax, TempArray, HmdtyArray);
i = 0;
}
i++;
}
void LuxInit(byte I2Caddress) {
byte luxBuffer[2];
Wire.beginTransmission(I2Caddress); // I2C address
Wire.write(0x10); // Switch to H-Mode 1Lux resolution 120ms
//Wire.write(0x11); // Switch to H-Mode2 0,5Lux resolution
//Wire.write(0x13); // Switch to L-Mode 4 Lux resolution 16ms
Wire.endTransmission();
}
int LuxRead(int I2Caddress) {
byte byteNumber = 0;
Wire.beginTransmission(I2Caddress); // I2C address
Wire.requestFrom(I2Caddress, 2); // Request fromm I2Caddress 2 bytes
while (Wire.available())
{
luxBuffer[byteNumber] = Wire.read(); // Read 2 bytes into array
byteNumber++;
}
Wire.endTransmission();
return byteNumber;
}
int TempHmdty() { ////////// TEMP-WERTE AUSLESEN
float h = dht.readHumidity();
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(dspH / 2, 20);
display.setTextColor(WHITE);
display.print("! Sensor error !");
display.display();
return 0;
}
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
// Werte abrunden
h1 = (int)(h + .5);
t1 = (int)(t + .5);
hic1 = (int)(hic + .5);
return t1, h1, hic1;
}
int Array(int t1, int h1) { // Array-Speicher aufbauen
int ArrayCounter;
if (ArrayCounter < arrNr) { // Solange Array nicht voll ist, zählt der Counter nach oben
ArrayCounter++;
}
if (ArrayCounter == arrNr) { // Fortlaufender Graph, alle Werte werden eins nach vorne gesetzt
for (int q = 1; q <= arrNr; q++) {
int tmp;
tmp = TempArray[q];
TempArray[q - 1] = tmp;
tmp = HmdtyArray[q];
HmdtyArray[q - 1] = tmp;
}
}
if (t1 > TempMax) {
TempMax = t1;
}
if (t1 < TempMin && t1 < 0) {
TempMin = t1;
}
TempArray[ArrayCounter] = t1;
HmdtyArray[ArrayCounter] = h1;
return *TempArray, *HmdtyArray, TempMin, TempMax;
}
void SerialPrint(float t1, float h1, int hic1, int luxValue) { // Serielle Ausgabe
Serial.print("Temp: ");
Serial.print(t1);
Serial.print(" ");
Serial.print("Hmdty: ");
Serial.print(h1);
Serial.print(" ");
Serial.print("HIC: ");
Serial.print(hic1);
Serial.print(" ");
Serial.print("Lux: ");
Serial.print(luxValue);
Serial.println();
}
void DisplayValuesInside(int t1, int h1, int hic1, int luxValue) { // Werte anzeigen
if (t1 < 0) { // Text der Temp-Anzeige bei Minus-Graden verkleinern
bigtext = 3;
}
else {
bigtext = 5;
}
display.setTextWrap(false);
display.clearDisplay();
// Headline
display.setTextSize(2);
display.setCursor(0, 0);
display.setTextColor(WHITE);
display.print("INSIDE");
display.drawLine(0, 17, dspW, 17, WHITE);
// Temperatur
display.setTextSize(bigtext);
display.setCursor(0, 24);
display.print(t1);
display.setTextSize(2);
display.print("C");
// Feuchtigkeit
display.drawLine(80, 17, 80, dspH, WHITE);
display.setCursor(90, 24);
display.print(h1);
display.print("%");
// HIC
//display.setCursor(90, 44);
//display.print(hic1);
//display.print("C");
// LUX
display.setTextSize(1);
display.setCursor(90, 44);
display.print(luxValue);
display.setCursor(110, 56);
display.print(" lx");
display.display();
}
void CoolingSymbol() { // Ventilator-Symbol
int x = 84;
int y = 3;
display.setCursor(x, y);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
display.print("COOLING");
display.drawLine(x - 1, y - 1, x + 41, y - 1, WHITE);
display.drawLine(x - 1, y + 8, x + 41, y + 8, WHITE);
display.drawLine(x - 1, y - 1, x - 1, y + 8, WHITE);
display.drawLine(x + 41, y - 1, x + 41, y + 8, WHITE);
display.display();
}
void CoolingStart() {
pinMode(13, HIGH);
}
void Graph(int TempMin, int TempMax, int TempArray[], int HmdtyArray[]) { // Temperaturverlauf
int TempMaxG, TempMinG, a, b, gc;
int g1 = 0;
TempMaxG = TempMax + 5;
if (TempMin < 0) {
TempMinG = TempMin - 5;
}
display.clearDisplay();
// Achsen
display.drawLine(20, 0, 20, dspH, WHITE); // y-Achse
display.drawLine(17, dspH - 1 + TempMinG, dspW, dspH - 1 + TempMinG, WHITE); // x-Achse
// Tempschwelle-Markierung
for (int tsg = 0; tsg <= 128; tsg = tsg + 8) {
display.drawPixel(20 + tsg, dspH + TempMinG - Tempschwelle * (dspH / (TempMax - TempMin)), WHITE);
}
// Achsenmarkierung
for (int a = 0; a < dspH; a = a + b) {
b = 10 / (dspH / (TempMaxG - TempMinG));
display.drawLine(19, a, 19, a, WHITE);
}
a = 0;
// Achsenbeschriftung
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(TempMaxG);
display.setCursor(0, dspH - 8);
display.print(TempMinG);
// Graph zeichnen
while (g1 < 108) {
for (int gc = 1; gc <= 2; gc++) { // Temp-Werte, jeder zweite Wert wird gezeichnet
display.drawPixel(g1 + 20, dspH + TempMinG - TempArray[g1] * (dspH / (TempMax - TempMin)), WHITE);
g1 = g1 + 2;
display.display();
}
gc = 1; // Feuchtigkeits-Werte, jeder vierte Wert wird gezeichnet
display.drawPixel(g1 + 2 + 20, dspH - HmdtyArray[g1 + 2], WHITE);
display.display();
}
g1 = 0;
display.clearDisplay();
}