Das geht hieraus hervor:
// Monoflop 3 OLED-Display einschalten
const byte displayOn = 5; // Taster für Trigger (gegen Masse) Pin 5
const byte outputPinDP = 6; // Ausgang für Display (if-Bedingung) Pin 6
displayOn hatte ich nur zur Fehlersuche beim Flattern der Anzeige verwendet. outputDP ist der Ausgang von Monoflop 3, welches das Display ein- und ausschaltet. Dieser Pin ist ausreichend.
Dein letzter Code bringt die Fehlermeldung "'schreibeDisplayVolt' was not declared in this scope".
Hier der komplette Sketch:
/* Solaranlage Garage
Ardunino Nano Port COM7, ATmega328P Old Bootloader)
Version 1.0
Code mit Unterstützung durch xy
Version mit intervall beim OLED -> Noch Fehler!
Datum: 30.12.2021
3x Monoflops (Kontakte/Taster entprellt) OK
3x Spannungsmesser OK (Widerstände noch ausmessen)
OLED-Display für Spannung/Strom mit Taste einschalten OK
To Do: Alarm Unterspannung (Bei Abschaltung durch SpÜ) noch Fehler
To Do: Referenzspannung aktivieren
To Do: Stromsensoren
To Do: Temperatursensor
*/
// OLED-Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Pausen
unsigned long startTime; // Startzeit
unsigned long startTime3; // Startzeit3
unsigned long startTime4; // Startzeit4
unsigned long currentTime; // Aktuelle Zeit Spannungsmesser Monitor
unsigned long currentTime3; // Aktuelle Zeit3 Solar
unsigned long currentTime4; // Aktuelle Zeit3 Accu 1
const unsigned long period2 = 2000; // Pausenlänge Stromsensoren
const byte solarPin = A0;
const byte accu1Pin = A1;
const byte accu2Pin = A2;
const unsigned int REF_VOLTAGE = 48; // entspricht 4,8 V
const unsigned int PIN_STEPS = 1024; // sollte das nicht 1023 sein?
const unsigned long multiplikator = 1000; // für Ganzzahlberechnung
unsigned int vout = 0, vin = 0;
unsigned int solarV = 0; // Solarzelle
unsigned int accu1V = 0; // Accu 1
unsigned int accu2V = 0; // Accu 2
// Spannungsteiler
// Wenn die Einheiten gleich sind,
// muss das nicht mit 0en ausgeschrieben werden
unsigned int R1 = 100; // resistance R1 (= 100 KOhm)
unsigned int R2 = 10; // resistance R2 (= 10 KOhm)
unsigned int R3 = 100; // resistance R1 (= 100 KOhm)
unsigned int R4 = 10; // resistance R2 (= 10 KOhm)
unsigned int R5 = 100; // resistance R1 (= 100 KOhm)
unsigned int R6 = 10; // resistance R2 (= 10 KOhm)
// Monoflop 1 Wechselrichter
const byte FB1Pin = 9; // FB1-Taster für Trigger (gegen Masse) Pin 9
const byte outputPinWR = 10; // Ausgang für LED, MOSFET, Relais Pin 10
const unsigned long Laufzeit1 = 1 * 3 * 1000UL; // Laufzeit Monoflop/WR (5 min.) -> 5*60*1000UL = 5 min. (Test: 3 sec.)
static uint32_t previousMillis1 = 0;
// Monoflop 2 Notbetrieb (Accu 1 Unterspannung)
const byte FB2Pin = 11; // FB2-Taster für Trigger (gegen Masse) Pin 11
const byte outputPinNB = 12; // Ausgang für LED, MOSFET, Relais Pin 12
const unsigned long Laufzeit2 = 1 * 2 * 1000UL; // Laufzeit Notbetrieb (5 min.) -> 5*60*1000UL = 5 min. (Test: 2 sec.)
static uint32_t previousMillis2 = 0;
// Monoflop 3 OLED-Display einschalten
const byte displayOn = 5; // Taster für Trigger (gegen Masse) Pin 5
const byte outputPinDP = 6; // Ausgang für Display (if-Bedingung) Pin 6
const unsigned long Laufzeit3 = 1 * 10 * 1000UL; // Anzeige OLED-Display (5 min.) -> 5*60*1000UL = 5 min. (Test: 10 sec.)
static uint32_t previousMillis3 = 0;
// Alarm bei Unterspannung Accu 1 (Spannungsüberwachung hat Accu 1 getrennt)
const byte inputUS = 7; // Unterspannung Pin 7
const byte outputPinUS = 8; // Ausgang für Piezo Pin 8
void setup()
{
pinMode(FB1Pin, INPUT_PULLUP);
pinMode(FB2Pin, INPUT_PULLUP);
pinMode(outputPinWR, OUTPUT);
pinMode(displayOn, INPUT_PULLUP);
pinMode(outputPinDP, OUTPUT);
pinMode(outputPinNB, OUTPUT);
pinMode(inputUS, INPUT_PULLUP);//
pinMode(outputPinUS, OUTPUT);
pinMode(solarPin, INPUT);
pinMode(accu1Pin, INPUT);
pinMode(accu2Pin, INPUT);
startTime = millis(); //initial start time
Serial.begin(9600);
Serial.println(F("Start"));
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) // Address 0x3D for 128x64
{
// Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
// suppress noise
if (vin < 0.09)
{
vin = 0.0;
}
}
///////////////////////////////////////////////////////////////////////////
void loop()
{
wechselRichter();
spannungsMessung();
oledDisplay();
}
void wechselRichter()
{
// Monoflop 1, Wechselrichter
if (digitalRead(FB1Pin) == LOW)
{
digitalWrite(outputPinWR, HIGH);
previousMillis1 = millis();
}
if (millis() - previousMillis1 > Laufzeit1 && digitalRead(outputPinWR) == HIGH)
{
digitalWrite(outputPinWR, LOW);
}
// Monoflop 2, Notbetrieb (Accu 100Ah Unterspannung)
if (digitalRead(FB2Pin) == LOW)
{
digitalWrite(outputPinNB, HIGH);
previousMillis2 = millis();
}
if (millis() - previousMillis2 > Laufzeit2 && digitalRead(outputPinNB) == HIGH)
{
digitalWrite(outputPinNB, LOW);
}
// Monoflop 3, OLED-Display einschalten
if (digitalRead(displayOn) == LOW)
{
digitalWrite(outputPinDP, HIGH);
previousMillis3 = millis();
}
if (millis() - previousMillis3 > Laufzeit3 && digitalRead(outputPinDP) == HIGH)
{
digitalWrite(outputPinDP, LOW);
}
}
// Alarm Unterspannung (Piezo bei Taster FB1 und Unterspannung) -> noch Fehler
//if (digitalRead(FB1Pin) == LOW && digitalRead(inputUS) == LOW) {
// digitalWrite(outputPinUS, HIGH);
//}
float voltMess(const byte messstelle)
{
uint32_t vout = 0;
switch (messstelle)
{
case 0:
vout = analogRead(solarPin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
//vout = 1023 * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R2 * multiplikator / (R1 + R2));
break;
case 1:
vout = analogRead(accu1Pin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R4 * multiplikator / (R3 + R4));
break;
case 2:
vout = analogRead(accu2Pin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R6 * multiplikator / (R5 + R6));
break;
}
return vout / 10.0;
}
// Spannungsmesser: Ausgabe Monitor
void spannungsMessung()
{
const unsigned long period1 = 2000; // Pausenlänge Spannungsmesser
// Spannungsmesser: Ausgabe Monitor
if (millis() - startTime >= period1) //Pause1 abgelaufen?
{
startTime += period1;
// A0
Serial.print(F("U Solar = "));
Serial.print(voltMess(0), 1);
Serial.println(F("V"));
// A1
Serial.print(F("U Accu 1 = "));
Serial.print(voltMess(1), 1);
Serial.println(F("V"));
// A2
Serial.print(F("U Accu 2 = "));
Serial.print(voltMess(2), 1);
Serial.println(F("V"));
}
}
// Ausgabe OLED-Display
void oledDisplay()
{
const uint32_t intervall = 2000;
static uint32_t lastmillis = 0;
static byte page = 0;
static uint16_t nachlauf = 0;
// Ausgabe OLED-Display
// OLED-Display einschalten
if (page == 0) // kein display gewählt
{
if (digitalRead(displayOn) == LOW)// und Taste gedrueckt
{
lastmillis = millis(); // setze Startzeit
nachlauf = 0;
page = 1;
Serial.println(F("Display ein!"));
}
}
else if (millis() - lastmillis >= intervall) // zeit abgelaufen
{
lastmillis += intervall;
if (page > 5) page = 1;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
Serial.print("page = "); // Test; entfällt später
Serial.println(page); // Test; entfällt später
switch (page)
{
case 1:
// Solar
display.println(F("Solarzelle"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);
schreibeDisplayRest();
break;
case 2:
// Accu 1
display.println(F("Accu 1"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);
schreibeDisplayRest();
break;
case 3:
// Accu 2
display.println(F("Accu 2"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);//
schreibeDisplayRest();
break;
case 4:
// Pause
display.println(F("Pause"));
//schreibeDisplayVolt();
//display.print(voltMess(page), 1);//
//schreibeDisplayRest();
break;
case 5:
if (digitalRead(displayOn) == HIGH)
{
if (nachlauf > 1000)
{
page = 0;
display.clearDisplay();
}
else nachlauf++;
}
break;
display.display();
}
page++;
}
}
Ich habe jetzt alle Änderungen zusammengefasst und die Tastenentprellung entfernt. Der OLED-Teil entspricht dann wieder #61, wobei der Zyklus immer mit Accu 1 beginnt. Für mein Teil muss der Zyklus nicht mit dem ersten Bildschirm beginnen, da nach Tastendruck eine Pause von bis zu 6 sec. folgen kann. Mir wäre eine sofortige Anzeige lieber. Ein nettes Feature wäre es, wenn auf erneuten Druck der Taste 3 (Monoflop 3) der aktuelle Bildschirm stehen bleiben würde. Dann könnte man die Werte z. B. beim Lauf des Torantriebes genau beobachten. Hast du dazu eine Idee? Ansonsten versuche ich es mit einem if zu realisieren. Der Solar-Regler hat eine ähnliche Funktion, wo ich die einzelnen Bildschirme durchklicken kann.
Bitte setze für deine Vorschläge auf diesem Sketch auf:
/* Solaranlage Garage
Ardunino Nano Port COM7, ATmega328P Old Bootloader)
Version 1.0
Code mit Unterstützung durch xy
Version mit intervall beim OLED
Datum: 30.12.2021
3x Monoflops (Kontakte/Taster entprellt) OK
3x Spannungsmesser OK (Widerstände noch ausmessen)
OLED-Display für Spannung/Strom mit Taste einschalten OK
To Do: Alarm Unterspannung (Bei Abschaltung durch SpÜ) noch Fehler
To Do: Referenzspannung aktivieren
To Do: Stromsensoren
To Do: Temperatursensor
*/
// OLED-Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Pausen
unsigned long startTime; // Startzeit
unsigned long startTime3; // Startzeit3
unsigned long startTime4; // Startzeit4
unsigned long currentTime; // Aktuelle Zeit Spannungsmesser Monitor
unsigned long currentTime3; // Aktuelle Zeit3 Solar
unsigned long currentTime4; // Aktuelle Zeit3 Accu 1
const unsigned long period2 = 2000; // Pausenlänge Stromsensoren
const byte solarPin = A0;
const byte accu1Pin = A1;
const byte accu2Pin = A2;
const unsigned int REF_VOLTAGE = 48; // entspricht 4,8 V
const unsigned int PIN_STEPS = 1024; // sollte das nicht 1023 sein?
const unsigned long multiplikator = 1000; // für Ganzzahlberechnung
unsigned int vout = 0, vin = 0;
unsigned int solarV = 0; // Solarzelle
unsigned int accu1V = 0; // Accu 1
unsigned int accu2V = 0; // Accu 2
// Spannungsteiler
// Wenn die Einheiten gleich sind,
// muss das nicht mit 0en ausgeschrieben werden
unsigned int R1 = 100; // resistance R1 (= 100 KOhm)
unsigned int R2 = 10; // resistance R2 (= 10 KOhm)
unsigned int R3 = 100; // resistance R1 (= 100 KOhm)
unsigned int R4 = 10; // resistance R2 (= 10 KOhm)
unsigned int R5 = 100; // resistance R1 (= 100 KOhm)
unsigned int R6 = 10; // resistance R2 (= 10 KOhm)
// Monoflop 1 Wechselrichter
const byte FB1Pin = 9; // FB1-Taster für Trigger (gegen Masse) Pin 9
const byte outputPinWR = 10; // Ausgang für LED, MOSFET, Relais Pin 10
const unsigned long Laufzeit1 = 1 * 3 * 1000UL; // Laufzeit Monoflop/WR (5 min.) -> 5*60*1000UL = 5 min. (Test: 3 sec.)
static uint32_t previousMillis1 = 0;
// Monoflop 2 Notbetrieb (Accu 1 Unterspannung)
const byte FB2Pin = 11; // FB2-Taster für Trigger (gegen Masse) Pin 11
const byte outputPinNB = 12; // Ausgang für LED, MOSFET, Relais Pin 12
const unsigned long Laufzeit2 = 1 * 2 * 1000UL; // Laufzeit Notbetrieb (5 min.) -> 5*60*1000UL = 5 min. (Test: 2 sec.)
static uint32_t previousMillis2 = 0;
// Monoflop 3 OLED-Display einschalten
const byte displayOn = 5; // Taster für Trigger (gegen Masse) Pin 5
const byte outputPinDP = 6; // Ausgang für Display (if-Bedingung) Pin 6
const unsigned long Laufzeit3 = 1 * 10 * 1000UL; // Anzeige OLED-Display (5 min.) -> 5*60*1000UL = 5 min. (Test: 10 sec.)
static uint32_t previousMillis3 = 0;
// Alarm bei Unterspannung Accu 1 (Spannungsüberwachung hat Accu 1 getrennt)
const byte inputUS = 7; // Unterspannung Pin 7
const byte outputPinUS = 8; // Ausgang für Piezo Pin 8
void setup()
{
pinMode(FB1Pin, INPUT_PULLUP);
pinMode(FB2Pin, INPUT_PULLUP);
pinMode(outputPinWR, OUTPUT);
pinMode(displayOn, INPUT_PULLUP);
pinMode(outputPinDP, OUTPUT);
pinMode(outputPinNB, OUTPUT);
pinMode(inputUS, INPUT_PULLUP);//
pinMode(outputPinUS, OUTPUT);
pinMode(solarPin, INPUT);
pinMode(accu1Pin, INPUT);
pinMode(accu2Pin, INPUT);
startTime = millis(); //initial start time
Serial.begin(9600);
Serial.println(F("Start"));
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) // Address 0x3D for 128x64
{
// Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
// suppress noise
if (vin < 0.09)
{
vin = 0.0;
}
}
///////////////////////////////////////////////////////////////////////////
void loop()
{
wechselRichter();
spannungsMessung();
oledDisplay();
}
void wechselRichter()
{
// Monoflop 1, Wechselrichter
if (digitalRead(FB1Pin) == LOW)
{
digitalWrite(outputPinWR, HIGH);
previousMillis1 = millis();
}
if (millis() - previousMillis1 > Laufzeit1 && digitalRead(outputPinWR) == HIGH)
{
digitalWrite(outputPinWR, LOW);
}
// Monoflop 2, Notbetrieb (Accu 100Ah Unterspannung)
if (digitalRead(FB2Pin) == LOW)
{
digitalWrite(outputPinNB, HIGH);
previousMillis2 = millis();
}
if (millis() - previousMillis2 > Laufzeit2 && digitalRead(outputPinNB) == HIGH)
{
digitalWrite(outputPinNB, LOW);
}
// Monoflop 3, OLED-Display einschalten
if (digitalRead(displayOn) == LOW)
{
digitalWrite(outputPinDP, HIGH);
previousMillis3 = millis();
}
if (millis() - previousMillis3 > Laufzeit3 && digitalRead(outputPinDP) == HIGH)
{
digitalWrite(outputPinDP, LOW);
}
}
// Alarm Unterspannung (Piezo bei Taster FB1 und Unterspannung) -> noch Fehler
//if (digitalRead(FB1Pin) == LOW && digitalRead(inputUS) == LOW) {
// digitalWrite(outputPinUS, HIGH);
//}
float voltMess(const byte messstelle)
{
uint32_t vout = 0;
switch (messstelle)
{
case 0:
vout = analogRead(solarPin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
//vout = 1023 * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R2 * multiplikator / (R1 + R2));
break;
case 1:
vout = analogRead(accu1Pin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R4 * multiplikator / (R3 + R4));
break;
case 2:
vout = analogRead(accu2Pin) * REF_VOLTAGE * multiplikator / PIN_STEPS;
vout = vout / (R6 * multiplikator / (R5 + R6));
break;
}
return vout / 10.0;
}
// Spannungsmesser: Ausgabe Monitor
void spannungsMessung()
{
const unsigned long period1 = 2000; // Pausenlänge Spannungsmesser
// Spannungsmesser: Ausgabe Monitor
if (millis() - startTime >= period1) //Pause1 abgelaufen?
{
startTime += period1;
// A0
Serial.print(F("U Solar = "));
Serial.print(voltMess(0), 1);
Serial.println(F("V"));
// A1
Serial.print(F("U Accu 1 = "));
Serial.print(voltMess(1), 1);
Serial.println(F("V"));
// A2
Serial.print(F("U Accu 2 = "));
Serial.print(voltMess(2), 1);
Serial.println(F("V"));
}
}
// Ausgabe OLED-Display
void oledDisplay()
{
const uint32_t intervall = 2000;
static uint32_t lastmillis = 0;
static byte page = 0;
// Ausgabe OLED-Display
// OLED-Display einschalten
if (digitalRead(outputPinDP) == HIGH) // Taste zum Einschalten für das OLED-Display gedrückt
{
if (page == 0) {
lastmillis = millis();
page = 1;
}
if (millis() - lastmillis >= intervall)
{
lastmillis += intervall;
page++;
if (page > 4) page = 1;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
Serial.print("page = "); // Test; entfällt später
Serial.println(page); // Test; entfällt später
switch (page)
{
case 1:
// Solar
display.println(F("Solarzelle"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);
schreibeDisplayRest();
break;
case 2:
// Accu 1
display.println(F("Accu 1"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);
schreibeDisplayRest();
break;
case 3:
// Accu 2
display.println(F("Accu 2"));
schreibeDisplayVolt();
display.print(voltMess(page), 1);//
schreibeDisplayRest();
break;
case 4:
// Temperatur
display.println(F("Temperatur"));
//schreibeDisplayVolt();
//display.print(voltMess(page), 1);//
//schreibeDisplayRest();
break;
}
display.display();
}
}
else {
display.clearDisplay(); // Display ausschalten
display.display();
page = 0;
}
}
void schreibeDisplayVolt()
{
display.println(F("----------"));
display.print(F("U = "));
}
void schreibeDisplayRest()
{
display.println(F(" V"));
display.println(F("I = 0.1 A"));
}