Hallo Arduino-Kameraden,
bei meinem Projekt möchte ich an mehreren Stellen Änderungen/Verbesserungen vornehmen. Für die "Hartgummilutscher" (Zit. Terrence Hill) aus der Programmier-Szene: ich bin noch nicht lange dabei. xD
Am Arduino Uno ist eine Regenwippe (von einer alten Wetterstation), zwei 1.3" OLEDs, das DS3231 RTC Modul und ein BH1750 Lichtsensor angeschlossen. Mit Ausnahme des Regensensors nutzen die Komponenten I2C, ihre Daten sind abrufbar. Weitere Sensoren sind zwecks Übersicht herausgenommen. Der Umstieg vom LCD auf zwei OLEDs ist nach vielem Herumgefrickel geglückt - ich habe nicht wie eigentlich erworben die SSD1306, sondern die SH1106 Controller. Der Verzicht auf die Funktion "u8g.begin()" im Setup löste das Problem sporadisch auftretender Hieroglyphen. Die Drahtbrücke eines Displays wurde von mir mit einem 470k OHM Widerstand geändert und die Datei "u8g_com_arduino_ssd_i2c.c" wie von olikraus im englischsprachigem Forum beschrieben angepasst:
uint8_t I2C_SLA = 0x3d2; // alternativ 0x3c2;
Beide OLEDs können jetzt im Sketch angesprochen werden. Ich hoffe nicht, dass mir die Änderung der Datei für zukünftige Projekte ein Bein stellt. Immerhin, es funzt. Die Sensorenmessung findet mit millis etwa minütlich statt, auf die Sekunde kommt es da nicht an. Aufgrund regelmäßiger Stromausfälle hatte ich daraus die Laufzeit des Arduino berechnet, was auch nicht sonderlich präzise ist aber als Information reichte.
Fragen
1.) Kann die Schriftart der U8glib zentriert werden? Im Netz stieß ich auf den command "setPrintPosCenter", was der Compiler aber nicht akzeptiert.
2.) Der Regensensor zählt zwar die Wippen-Bewegungen, allerdings nur dann, wenn der Arduino den Pin ständig abfragt. Wegen der Bildschirmanzeigen -hier auch noch verkürzt- kann er das jedoch nicht. Mit der <INTERVAL.h> oder der Nachtwächter-Funktion von "agmue", "combie" & Co. komme ich jedoch nicht zurecht. Daraufhin habe ich alle Anzeigen in die Funktion "LCDactivityStats" ausgegliedert - ist zwar im Endergbnis der gleiche Käse, lässt sich aber zu Testzwecken schnell aus dem Sketch völlig ausklammern.
3.) In der Vergangenheit hatte ich den Niederschlag pro Tag, Woche und Monat akkumuliert und per RTC um Mitternacht bzw. zu Wochenbeginn genullt. Da ein Motorkugelventil die Wasserzufuhr einer Gardena-Bewässerungsanlage unterbinden soll, ist diese Methode ziemlich unprofessionell: Besser wäre die fortlaufende Zählung der Regenmenge aus den letzten 24 Stunden, 3 Tagen und 7 Tagen - nur: wie wird das programmiert? Der Monatswert ist nicht so wichtig und dient eher der allgemeinen Auskunft für die Gesamtmenge des Niederschlages aus dem aktuellen Monat.
#define SCREEN_MILLISECONDS 8000
#define DS3231_I2C_ADDRESS 0x68
#define RainPin 2
#include <Wire.h> // DS3231 RTC, BH1750, RainGauge
#include <BH1750.h> // BH1750 Light Sensor
BH1750 lightMeter(0x23);
uint16_t lux;
#include "ds3231.h" // DS3231 RTC with AT24C32 Chip
#include "Wire.h" // https://www.maximintegrated.com/en/products/digital/real-time-clocks/DS3231.html
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
char recv[128];
byte decToBcd(byte val) { // Convert normal decimal numbers to binary coded decimal
return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers
return ((val / 16 * 10) + (val % 16));
}
float temperature_rtc; // Temperatur RTC-Modul
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI
extern uint8_t I2C_SLA; // Changed I2C entry at > Arduino\libraries\U8glib\src\clib
bool RainHigh=false; // RainGauge
const float LowAmt = 0.005;
const float HiAmt = 0.005;
float rainLast24h = 0.000;
float rainLast3Days = 0.000;
float rainLast7Days = 0.000;
float rainMonth = 0.000;
unsigned long resetLoops = 1; // Counting overall loops startig with every reset
unsigned long currentMillisMeasurements = millis(); // Sensor Measurement and Runtime
long previousMillisMeasurements = 0;
long intervalMeasurements = 60000;
unsigned int totalMeasurements = 0;
void setup(void) {
Serial.begin(9600);
Wire.begin(); // Initialize the I2C bus for DS3231, BH1750, RainGauge
// UHRZEIT NEU EINSPIELEN
// setDS3231time(15,2,10,4,28,2,18); // e.g. Mittwoch, 28. Februar 2018, 10:02:15 Uhr
// BH1750: begin returns a boolean that can be used to detect setup problems
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE))
Serial.println(F("BH1750 Advanced begin"));
else
Serial.println(F("Error initialising BH1750"));
pinMode(RainPin, INPUT); // RainGauge
if (digitalRead(RainPin)==HIGH)
RainHigh=true;
else
RainHigh=false;
u8g.setFont(u8g_font_6x13); // OLED Font 9px height
} // END SETUP
Die Schleife sieht dann folgendermaßen aus:
void loop(void) {
currentMillisMeasurements = millis(); // Calculation for sensorMeasurements-function
// SENSOR-DATENERHEBUNG
if(resetLoops == 1 || currentMillisMeasurements - previousMillisMeasurements > intervalMeasurements) {
sensorMeasurements();
previousMillisMeasurements = currentMillisMeasurements;
}
// Niederschlag
if ((RainHigh==false)&&(digitalRead(RainPin)==HIGH)) {
RainHigh=true;
rainLast24h+=LowAmt;
rainLast3Days+=LowAmt;
rainLast7Days+=LowAmt;
rainMonth+=LowAmt;
}
if ((RainHigh==true)&&(digitalRead(RainPin)==LOW)) {
RainHigh=false;
rainLast24h+=HiAmt;
rainLast3Days+=HiAmt;
rainLast7Days+=LowAmt;
rainMonth+=HiAmt;
}
LCDactivityStats(); // OLED-INFORMATIONSSCHLEIFE
resetLoops++;
} // END LOOP
void sensorMeasurements() {
lux = lightMeter.readLightLevel(); // BH1750 Light calculations
temperature_rtc = DS3231_get_treg(); // Read temperature from DS3231 RTC
totalMeasurements++;
} // END - sensorMeasurements
void LCDactivityStats() {
I2C_SLA = 0x3d*2; // left display
// I2C_SLA = 0x3c*2; // right display
u8g.firstPage();
do {
u8g.drawStr(24, 9, "EINSTELLUNGEN");
u8g.drawLine(0, 11, 128, 11);
u8g.setPrintPos(3, 25);
if (dayOfMonth < 10)
u8g.print("0");
u8g.print(dayOfMonth, DEC);
u8g.print(".");
if (month < 10)
u8g.print("0");
u8g.print(month, DEC);
u8g.print(".");
u8g.print("20");
u8g.print(year, DEC);
u8g.print(" ");
if (hour < 10)
u8g.print("0");
u8g.print(hour, DEC);
u8g.print(":");
if (minute < 10)
u8g.print("0");
u8g.print(minute, DEC);
u8g.print(" UCT");
u8g.setPrintPos(0, 38);
u8g.print("RTC Temp. ");
u8g.print(temperature_rtc, 2);
u8g.print("*C");
u8g.setPrintPos(0, 51);
u8g.print("Helligkeit ");
u8g.print(lux);
u8g.print(" lux");
u8g.setPrintPos(0, 64);
u8g.print("Laufzeit ");
if (totalMeasurements < 288) {
u8g.print("<24 Stunden");
} else if (totalMeasurements >= 288 && totalMeasurements < 576) {
u8g.print("ein Tag");
} else if (totalMeasurements >= 576 && totalMeasurements < 846) {
u8g.print("2 Tage");
} else if (totalMeasurements >= 846 && totalMeasurements < 1152) {
u8g.print("3 Tage");
} else if (totalMeasurements >= 1152 && totalMeasurements < 1440) {
u8g.print("4 Tage");
} else if (totalMeasurements >= 1440 && totalMeasurements < 1728) {
u8g.print("5 Tage");
} else if (totalMeasurements >= 1728 && totalMeasurements < 2016) {
u8g.print("6 Tage");
} else if (totalMeasurements >= 2016) {
u8g.print(">1 Woche");
}
} while (u8g.nextPage());
// I2C_SLA = 0x3d*2; // left display
I2C_SLA = 0x3c*2; // right display
u8g.firstPage();
do {
u8g.drawStr(27, 9, "NIEDERSCHLAG");
u8g.drawLine(0, 11, 128, 11);
u8g.setPrintPos(0, 25);
u8g.print(" 24h ");
u8g.print(rainLast24h, 2);
u8g.print(" Liter");
u8g.setPrintPos(0, 38);
u8g.print(" 3 Tage ");
u8g.print(rainLast3Days, 2);
u8g.print(" Liter");
u8g.setPrintPos(0, 51);
u8g.print(" 7 Tage ");
u8g.print(rainLast3Days, 2);
u8g.print(" Liter");
u8g.setPrintPos(0, 64);
u8g.print(" Monat ");
u8g.print(rainMonth);
u8g.print(" Liter");
} while (u8g.nextPage());
delay(SCREEN_MILLISECONDS);
} // END - LCDactivityStats
Die Funktionen der RTC (void setDS3231time, void readDS3231time und void displayTime) sind ebenso wie Serial.prints wg. der Zeichenbegrenzung herausgenommen.
Für leicht verständliche Hilfe und Verbesserungen bin ich sehr dankbar.