Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:flaschenkuehler:programmversion_0.2

Flaschenkühler - Programmversion 0.2

Diese Programmversion bindet das OLED-Display ein. Für MISO und SCLK werden die Hardwarepins verwendet. Es könnten auch andere digitale Pins verwendet werden, was sich aber negativ auf die Performanz auswirken soll. Die anderen Pins können ohne Einbußen bei der Performanz frei gewählt werden. Außerdem wurden die beiden Taster integriert, mit denen perspektivisch die Solltemperatur eingestellt können werden soll. Die eingestellte Solltemperatur wird im EEPROM gespeichert. Darüber hinaus wird die Drehzahl des Lüfters überwacht: Sollte der Lüfter sich drehen, dreht sich aber nicht, wird eine Fehlfunktion auf dem Display angegeben. Schließlich wurde noch ein Betriebsstundenzähler programmiert.

Der Code wurde hier und da optimiert, so dass er schneller ausgeführt wird. Beispielsweise wird der Thermistor nun nur noch alle 10 Millisekunden ausgelesen und die Isttemperatur berechnet. Außerdem werden nur die Bereiche auf dem Display neu aufgebaut, die sich geändert haben.

OLED-Display

Das OLED-Display ist an den folgenden Pins angeschlossen:

Arduino Nano    Adafruit OLED Breakout Board
GND             GND (G)
5V              VIN (+)
D13             SCLK (CL)
D11             MOSI (SI)
D5              DC
D6              OLEDCS (OC) (besser bekannt als Chip Select (CS))
D7              RST (R)

Um das OLED zu testen werden verschiedene Variablen angezeigt: die Solltemeratur, die Isttemperatur am Thermistor und die Drehzahl des Lüfters. In der fertigen Programmversion wird freilich die Solltemperatur des Kühlbechers einstellbar sein, und das Peltier-Element entsprechend geregelt werden.

Hilfreiche Webseiten:

Die Datenübertragung zum Display ist ziemlich langsam. Um die Ausführung des Codes zu beschleunigen, werden immer nur die Bildschirmbereiche aktualisiert, die sich geändert haben.

Betriebsstunden, Taster, EEPROM

Außerdem werden die Betriebsstunden viertelstundengenau gezählt und im EEPROM gespeichert. Die viertelstundengenaue Zählweise schont das EEPROM. Später soll eine Funktion programmiert werden, die z.B. alle 100 Stunden zur Reinigung des Geräts (insbesondere des Lüfters) auffordert.

Das Programm fragt einmal pro Schleife die beiden Taster ab. Diese Lösung ist gegenüber der Nutzung von Interrupts nicht die erste Wahl, weil der Arduino Nano jedoch nur zwei interruptfähige Pins hat (Pin 2 und Pin 3) und einer der beiden Pins (3) für die PWM-Ansteuerung des Peltier-Elements verwendet wird, fällt diese Variante aus. Die Taster sind entprellt und lösen erst beim Loslassen aus. Die Solltemperatur wird im EEPROM gespeichert.

Sowohl für den Betriebsstundenzähler als auch für die Speicherung der Solltemperatur müssen Variablen mit dem Dateityp float bzw. double im EEPROM gespeichert werden. Zu diesem Zweck wurde die Bibliothek EEPROMex eingebunden.

To dos:

  • Es soll eine Sicherungsschaltung programmiert werden, die das Peltierelement ausschaltet, falls der Lüfter blockiert. Das erscheint mir sinnvoll, da vor dem Lüfter kein Schutzgitter montiert wird, um Luftgeräusche zu minimieren.
  • Es soll zwischen verschiedenen Anzeigemodi gewechselt werden können, indem die Taster länger gedrückt werden.
// Flaschenkühler - Programmversion 0.2
// Diese Version steuert einen PC-Lüfter mit 4-Pin-Anschluss ...
// ... liest das Tachosignal aus ...
// ... berechnet die Drehzahl des Lüfters ...
// ... liest einen Thermistor aus und berechnet die Temperatur ...
// ... stellt über ein Poti die ZieltemperatureHotSidee ein ...
// ... regelt den Lüfter mit einem PID-Modul ...
// ... zeigt verschiedene Werte auf einem OLED-Display an ...
// ... zählt die Betriebsstunden (viertelstundengenau) und speichert sie im EEPROM ...
// ... pollt die Taster und speichert die Solltemperatur im EEPROM.

//------------------------- Eingebundene Bibliotheken ---------------------//
#include <Adafruit_GFX.h>         // Grafik-Bibliothek für OLED-Display
#include <Adafruit_SSD1351.h>     // Bibliothek für OLED-Display (Adafruit OLED Breakout Board 1.27")
#include <SPI.h>                  // Bibliothek Serial Peripheral Interface (SPI)
#include <PWM.h>                  // Bibliothek für Änderung der Frequenz der Timer
#include <RunningAverage.h>       // Bibliothek für Berechnung von Mittelwerten
#include <PID_v1.h>               // Bibliothek für PID-Regler
#include <EEPROMex.h>             // Bibliothek für Lesen und Schreiben des EEPROMS

//------------------------- Definition der Inputs und Outputs ---------------------//
#define potiPin         A0        // Input-Pin für den Lüfter
#define thermistorPin   A1        // Input-Pin für den Thermistor
#define tachoPin        2         // Pin für Tachosignal des Lüfters
#define peltierPin      3         // PWM-Pin für Peltier-Element (hier zunächst nur als Funktionstest)
#define powerPin        4         // Schaltet den MOSFET für den Lüfter
#define dc              5         // 
#define cs              6         // Chip Select
#define rst             7         // Reset
#define button1Pin      8         // Taster 1
#define fanPin          9         // PWM-Pin für Lüfter
#define button2Pin      12        // Taster 2


//------------------------- Definition der Farben ---------------------//
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

//------------------------- Definition der Variablen ---------------------//
int button1state = HIGH;       // aktuelles Signal vom Tasterpin
int button1pressed = 0;        // abfragen ob Taster gedrückt war
int button2state = HIGH;       // aktuelles Signal vom Tasterpin
int button2pressed = 0;        // abfragen ob Taster gedrückt war
int debouncetime = 5;          // Zeit für Entprellung ggf. anpassen
unsigned long button1time = 0;
unsigned long button2time = 0;


float thermistorValue = 0;         // Variable in der der Wert des Thermistors gespeichert wird
int potiValue = 0;                 // variable to store the value coming from the sensor

// PWM Frequenzen
uint16_t frequencyFan = 25000;     // PWM-Frequenz für den Lüfter (in Hz)
uint16_t frequencyPeltier = 50000; // PWM-Frequenz für den Lüfter (in Hz)

// Lüfter
int tachoSignal;                   // Tachosignal
uint32_t pulseOn = 0;              // Ansteigende Signalflanke (Variablenformat nicht verändern!)
uint32_t pulseOff = 0;             // Abfallende Signalflanke (Variablenformat nicht verändern!)
uint32_t duration;                 // Zeit in Mikrosekunden zwischen ansteigender und abfallender Flanke (Variablenformat nicht verändern!)
bool high = false;                 // Statevariable
int rpm = 0;                       // Drehzahl des Lüfters in U/Min
float rpmAverage = 0;              // Gemittelte Drehzahl des Lüfters in U/min
bool fanAlert = false;             // Wird wahr, wenn der Lüfter blockiert ist
bool fanAlertState = true;
unsigned long fanAlertDelay = 2000;// Gibt die Verzögerung des Alarms "Lüfterfehlfunktion" in Millisekunden an
unsigned long previousMillis = 0;


// Temperaturen
float temperatureHotSide = 0;

// Betriebszeit
float operatingTime;               // Betriebsstunden als Dezimalwert
long lastTime = 0;

// Adressen im EEPROM
int addrOperatingTime = 0;         // Startadresse für eine Variable im Datentyp float (4 Byte!)
int addrTargetTemp = 4;            // Startadresse für eine Variable im Datentyp double (8 Byte!) 

// Definiert das OLED
Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst);

// Informationsanzeige
bool refreshPeltier = true;
bool refreshTargettemp = true;
//bool refreshActualtemp = true;
bool refreshFan = true;

// Instantiiert RunningAverage-Objekte zur Bechnung von Mittelwerten
RunningAverage averageRPM(25);         // Mittelwert aus 25 Messungen
RunningAverage averageThermistor(10);  // MIttelwert aus 10 Messungen

// Definiert den PID-Regler
double Setpoint, Input, Output;
double Kp=2, Ki=5, Kd=1;
PID fanPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE);

// Definiert die Tracking-Variablen für die IF-Abfragen
unsigned long previousMillisCalculateTemperatures = 0;// Berechnung der Temperaturen
unsigned long previousMillisCalculateFanSpeed = 0;    // Berechnung der Drehzahl des Lüfters
unsigned long previousMillisDisplayActualtemp = 0;    // Ausgabe der Ist-Temperatur an das OLED-Display
unsigned long previousMillisDisplayFanSpeed = 0;      // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display
unsigned long previousMillisSerialPrint = 0;          // Ausgabe an die serielle Schnittstelle

// Definiert die Intervalle für die IF-Abfragen in Millisekunden
const unsigned long intervalCalculateTemperatures = 10;
const unsigned long intervalCalculateFanSpeed = 100;  // Berechnung der Drehzahl des Lüfters
const unsigned long intervalDisplayActualtemp = 500;  // Ausgabe der Ist-Temperatur an das OLED-Display
const unsigned long intervalDisplayFanSpeed = 500;    // Ausgabe der gemittelten Lüfterdrehzahl an das OLED-Display
const unsigned long intervalSerialPrint = 500;        // Ausgabe an die serielle Schnittstelle

int loopCounter = 0;


//------------------------- Setup ---------------------//
void setup() {
  Serial.begin(115200);
 
  // Initialisiert das OLED-Dispaly
  tft.begin();
  
  // Definiert die Pins
  pinMode(tachoPin, INPUT_PULLUP);                    // Tachosignal des Lüfters
  pinMode(powerPin, OUTPUT);                          // Schaltet den MOSFET für den Lüfter
  pinMode(fanPin, OUTPUT);                            // PWM-Signal für Lüfter
  pinMode(peltierPin, OUTPUT);                        // PWM-Signal für Peltier-Element
  pinMode(button1Pin, INPUT_PULLUP);                  // Intur Taster 1
  pinMode(button2Pin, INPUT_PULLUP);                  // Input Taster 2
  
  // Initialisiert timer1 und timer2 (timer0 bleibt unberührt)
  InitTimersSafe(); 

  // Definiert die Frequenzen für die angegebenen Pins
  bool successFan = SetPinFrequencySafe(fanPin, frequencyFan);
  bool successPeltier = SetPinFrequencySafe(peltierPin, frequencyPeltier);

  /*
  //if the pin frequency was set successfully, turn pin 13 on
  if(successFan) {
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);
    Serial.print("PWM frequency PIN D9 and D10 is set to: "); Serial.println(frequencyFan);
  }
  if(successPeltier) {
    Serial.print("PWM frequency PIN D3 and D11 is set to: "); Serial.println(frequencyPeltier);
  }
  */
  // Initialisiert die PID-Regler
  fanPID.SetMode(AUTOMATIC);

  // Liest die im EEPROM gespeicherten Variablen aus
  operatingTime = EEPROM.readFloat(addrOperatingTime);
  Setpoint = EEPROM.readDouble(addrTargetTemp);

  // Stellt sicher, dass im ersten Durchlauf der Programmschleife nicht fälschlicherweise eine Lüfterfehlfunktion gemeldet wird
  previousMillis = fanAlertDelay;
  
  // Meldung "Klar zum Start!"
  Serial.println("<Arduino is ready! Turn the potentiometer, please ...>"); 
  Serial.print("<Operating Time of the System: "); Serial.print(operatingTime); Serial.println(" hours>");
  
  // Startbildschirm
  tft.fillScreen(BLACK);
  tft.setCursor(25, 32);
  tft.setTextColor(WHITE, BLACK);
  tft.setTextSize(0);
  tft.print("Flaschenk"); tft.print((char)154); tft.print("hler");
  tft.setCursor(22, 60);
  tft.print("Programmversion");
  tft.setCursor(45, 75);
  tft.setTextSize(2);
  tft.print("0.2");
  tft.setCursor(10, 108);
  tft.setTextSize(0);
  tft.print("Betriebsstunden:");
  tft.setCursor(10, 120);
  tft.print(operatingTime); tft.print(" Stunden"); 
  
  delay(1000);
  tft.fillScreen(BLACK);
}


//------------------------- Loop ---------------------//
void loop() {
  // Aktuelle Zeit abfragen
  unsigned long currentMillis = millis();

loopCounter++;


//------------------------- Abfrage der Taster ---------------------//
// Lesen und entprellen des Tasters
  button1state = digitalRead(button1Pin);
  button2state = digitalRead(button2Pin);
  
  // Wenn der Taster 1 gedrückt ist...
  if (button1state == LOW)
  {
    button1time = millis();                      // aktualisiere tasterZeit
    button1pressed = 1;                          // speichert, dass Taster gedrückt wurde
  }
 
  // Wenn die gewählte entprellZeit vergangen ist und der Taster gedrückt war...
  if ((millis() - button1time > debouncetime) && button1pressed == 1) {
    button1pressed = 0;                        // setzt gedrückten Taster zurück
    Setpoint = Setpoint + 0.5;
    EEPROM.updateDouble(addrTargetTemp, Setpoint);
    Serial.print("Updated Setpoint: "); Serial.println(Setpoint);
    refreshTargettemp = true;
    if (Setpoint == 30) {
      Setpoint = 30;                   // setzt die NeoPixel zurück
    }
    //Serial.print("Setpoint: "); Serial.print(Setpoint);
  }
  
   // Wenn der Taster 2 gedrückt ist...
  if (button2state == LOW)
  {
    button2time = millis();                      // aktualisiere tasterZeit
    button2pressed = 1;                          // speichert, dass Taster gedrückt wurde
  }
 
  // Wenn die gewählte entprellZeit vergangen ist und der Taster gedrückt war...
  if ((millis() - button2time > debouncetime) && button2pressed == 1) {
    button2pressed = 0;                        // setzt gedrückten Taster zurück
    Setpoint = Setpoint - 0.5;
    EEPROM.updateDouble(addrTargetTemp, Setpoint);
    Serial.print("Updated Setpoint: "); Serial.println(Setpoint);
    refreshTargettemp = true;
    if (Setpoint == 0) {
      Setpoint = 0;                   // setzt die NeoPixel zurück
    }
    //Serial.print("Setpoint: "); Serial.print(Setpoint);
  } 
  

//------------------------- Auslesen der Thermistoren und Berechnung der Temperaturen ---------------------//  
  if ((unsigned long)(currentMillis - previousMillisCalculateTemperatures) >= intervalCalculateTemperatures) {
    // Lese die analogen Inputs aus
    potiValue = analogRead(potiPin);                    // Poti
    thermistorValue = analogRead(thermistorPin);        // Thermistor
    averageThermistor.addValue(thermistorValue);        // Wert wird an Running Average übergeben 
  
    // Berechnung der Temperatur
    thermistorValue = averageThermistor.getAverage();   // Der Mittelwert wird eingelesen
    thermistorValue = 1023 / thermistorValue - 1;       
    thermistorValue = 10000 / thermistorValue;          // Der Wert wird in einen Widerstand umgerechnet
  
    //float temperatureHotSide;
    temperatureHotSide = thermistorValue / 10000;       // (R/Ro)
    temperatureHotSide = log(temperatureHotSide);       // ln(R/Ro)
    temperatureHotSide /= 3950;                         // 1/B * ln(R/Ro)
    temperatureHotSide += 1.0 / (25 + 273.15);          // + (1/To)
    temperatureHotSide = 1.0 / temperatureHotSide;      // Invert
    temperatureHotSide -= 273.15;                       // convert to C
    
    previousMillisCalculateTemperatures = currentMillis;
  }

//------------------------- Regelung des Lüfters (TEST) ---------------------// 
  Input = temperatureHotSide;                                 // Input ist die temperatureHotSide des Thermistors in *C
  fanPID.Compute();                                   // PID-Regler wir aufgerufen
  pwmWrite(fanPin, Output);                           // Gibt den Output des PID-Reglers an den Lüfter

  // Wenn der Output des PID-Reglers Null ist, wird der Lüfter ausgeschaltet.
  if (Output > 0) {
    digitalWrite(powerPin, HIGH);
    //Serial.print("HIGH"); Serial.print("; ");
  }
  else {
    digitalWrite(powerPin, LOW);
    //Serial.print("LOW"); Serial.print("; ");
  }
  
  //use this functions instead of analogWrite on 'initialized' pins
  pwmWrite(peltierPin, potiValue / 4);                // Nur zu Testzwecken


//------------------------- Tachosignal und Drehzahl des Lüfters ---------------------//
  // Messung der Pulsweite des Tachosignals
  tachoSignal = digitalRead(tachoPin);
  if (tachoSignal == HIGH && high != true) {          // Zeit in micros bei ansteigender Flanke
    pulseOn = micros();
    high = true;
  }
  else if (tachoSignal == LOW && high == true) {
    pulseOff = micros();                              // Zeit in micros bei fallender Flanke 
    high = false;
    duration = pulseOff - pulseOn;                    // Aus der Differenz wir die Dauer berechnet, die das Tachosignal HIGH ist
    if (duration > 7000 && duration < 150000) {       // Liegt die Variable über bzw. unter den angegebenen Werten, liegt ein Messfehler vor
      rpm = float(100000 * 2 * 60 / duration);        // Berechnung der RPM
    }
    else {
      rpm = 0;
    }
    //averageRPM.addValue(rpm);
  }

  // Berechnung der gemittelten Drehzahl des Lüfters
  if ((unsigned long)(currentMillis - previousMillisCalculateFanSpeed) >= intervalCalculateFanSpeed) {
    averageRPM.addValue(rpm);                         // Aktualisiert das RunningAverage-Objekt 
    
    // Wenn der Lüfter angehalten wird, soll die Drehzahl "0" angezeigt werden
    if (Output == 0) {
      rpm = 0;
      averageRPM.addValue(rpm);
    }

    // Liest die durchschnittliche Drehzahl aus und speichert das Ergebnis in eine Variable
    rpmAverage = averageRPM.getAverage();

    // Meldet eine Fehlfunktion des Lüfters, wenn das Tachosignal "0" ist, obwohl der Lüfter sich drehen sollte
    if (Output > 0) {                                    // Wenn der Lüfter sich drehen sollte ...
      if (rpmAverage == 0) {                             // ... aber die gemittelte Drehzahl gleich "0" ist ...      
        if (millis() - previousMillis > fanAlertDelay) { // ... und eine definierte Zeit verstrichen ist.
          previousMillis = millis();
          fanAlert = true;
          fanAlertState = true;
          Serial.println("Fan blocked!");
          refreshFan = true; 
        } 
      }
      else if (rpmAverage > 0) {                    // ... und die gemittelte Drehzahl größer "0" ist ...
        fanAlert = false;
      }
    }
    else if (Output == 0) {                         // Wenn der Lüfter sich nicht drehen soll kann nicht festgestellt werden, ob er blockiert ist.
      fanAlert = false;
      previousMillis = millis();                     // Muss aktualisiert werden, damit
      if (fanAlert != fanAlertState) {
        refreshFan = true;
        fanAlertState = false;
      }
    }
  
  previousMillisCalculateFanSpeed = currentMillis;
  }


//------------------------- Betriebsstunden ---------------------//
// Die Betriebsstunden werden alle 15 Minuten im EEPROM gespeichert. Die Einheit der Variable operatinTime ist also 0,25 Stunden.
  if (millis() - lastTime >= 900000) {
    operatingTime = operatingTime + 0.25;
    lastTime = millis();
    EEPROM.updateFloat(addrOperatingTime, operatingTime);
    Serial.print("Updated operatingTime: "); Serial.println(operatingTime);
  }


//------------------------- Ausgabe an das Display ---------------------//
  // Anzeige Infobereich Peltier-Element
  if (refreshPeltier == true) {
    
    tft.setCursor(0, 32);
    tft.setTextColor(WHITE, BLACK);  
    tft.setTextSize(0);
    tft.print("Infos Peltier-Element");
    refreshPeltier = false;
  }
  
  // Anzeige Infobereich Zieltemperatur
  if (refreshTargettemp == true) {
    tft.setCursor(15, 49);
    tft.setTextColor(YELLOW, BLACK);  
    tft.setTextSize(0);
    tft.print("Solltemperatur");
    tft.setCursor(15, 62);
    tft.setTextSize(2);
      if (Setpoint < 10.00) {
      tft.print("0");
    }
    tft.print(Setpoint); tft.print(" "); tft.print((char)247); tft.print("C"); 
    tft.setTextColor(BLACK, BLACK);
    tft.print((char)218);
    refreshTargettemp = false;
  }
  
  // Anzeige Infobereich Isttemperatur
  if ((unsigned long)(currentMillis - previousMillisDisplayActualtemp) >= intervalSerialPrint) {
    tft.setCursor(15, 85);
    tft.setTextColor(RED, BLACK);
    tft.setTextSize(0);
    tft.print("Isttemperatur");  
    tft.setCursor(15, 98);
    tft.setTextSize(2);
    if (temperatureHotSide < 10.00) {
      tft.print("0");
    }
    tft.print(temperatureHotSide); tft.print(" "); tft.print((char)247); tft.print("C");
    tft.setTextColor(BLACK, BLACK);
    tft.print((char)218);
    //refreshActualtemp = false;
    previousMillisDisplayActualtemp = currentMillis;
  }

  // Anzeige Infobereich Lüfter
  if (fanAlert == true) {
    if (refreshFan == true) {
      tft.setCursor(0, 120);  
      tft.setTextSize(0);
      tft.setTextColor(RED, BLACK);
      tft.print("L"); tft.print((char)154); tft.print("fterfehlfunktion!"); 
      refreshFan = false;
    }
  }  
  else if (fanAlert == false) {
    if (rpmAverage > 0) {                    // Wenn die Drehzahl größer "0" ist, aktualisiere den Anzeigebereich all 500 Millisekunden
      if ((unsigned long)(currentMillis - previousMillisDisplayFanSpeed) >= intervalDisplayFanSpeed) { 
        tft.setCursor(0, 120);  
        tft.setTextSize(0);
        tft.setTextColor(WHITE, BLACK);
        tft.print("L"); tft.print((char)154); tft.print("fter ");  tft.print(int(rpmAverage)); tft.print(" U/min");
        tft.setTextColor(BLACK, BLACK);
        for (int i=0; i<5; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden
          tft.print((char)218);
        }
        refreshFan = true;
        previousMillisDisplayFanSpeed = currentMillis;
      }
    }  
    else if (rpmAverage == 0) {
      if (refreshFan == true) {
        tft.setCursor(0, 120);  
        tft.setTextSize(0);
        tft.setTextColor(WHITE, BLACK);
        tft.print("L"); tft.print((char)154); tft.print("fter aus"); 
        tft.setTextColor(BLACK, BLACK);
        for (int i=0; i<12; i++) {            // Füllt die Zeile mit schwarzen Kästchen; i muss ggf. angepasst werden
          tft.print((char)218);
        }
        refreshFan = false;
      }
    }
  }
  

//------------------------- Ausgabe an die serielle Schnittstelle ---------------------//
  if ((unsigned long)(currentMillis - previousMillisSerialPrint) >= intervalSerialPrint) {
    
    Serial.print("Setpoint: ");Serial.print(Setpoint);
    Serial.print("; Input: ");Serial.print(Input);
    Serial.print("; Output: ");Serial.print(Output);
    //Serial.print("; pulseOn: ");Serial.print(pulseOn);
    //Serial.print("; pulseOff: ");Serial.print(pulseOff);
    //Serial.print("; Duration: "); Serial.print(duration);
    Serial.print("; RPM: "); Serial.print(rpm);
    Serial.print("; average RPM: "); Serial.print(rpmAverage);
    Serial.print("; fanAlert: "); Serial.print(fanAlert);
    //Serial.print("; temperatureHotSide: "); Serial.println(temperatureHotSide);
    Serial.print("; operatingTime: "); Serial.print(operatingTime); 
    Serial.print("; Loops: "); Serial.println(loopCounter);
    loopCounter = 0;
    
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisSerialPrint = currentMillis;
  }
}

Der Sketch verwendet 19020 Bytes (61%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes. Globale Variablen verwenden 1054 Bytes (51%) des dynamischen Speichers, 994 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Tags: #Arduino #Flaschenkühler #Nano #OLED

arduino/flaschenkuehler/programmversion_0.2.txt · Zuletzt geändert: 18.05.2023 12:34 von 127.0.0.1