Ersatz für delay(); in einem Arduino Nano gesucht?

2 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet
ich benötige einen Ersatz für Delay, der die Ausführung von Subroutinen nicht behindert.

Dann solltest du deinen Code von einer synchronen "Super Loop" auf die Verwendung von Timern umstellen. Grob gesagt sagst du dem Timer, dass er ein bestimmtes Stück Code mittels Interrupt nach einer bestimmten Zeit bzw. in einem bestimmten Intervall aufrufen soll.

Hier wäre eine Bibliothek, die dir dabei hilft (ohne Gewähr, ob die besonders gut ist oder ob es nicht bessere gibt): https://www.arduino.cc/reference/en/libraries/timerone/


stealthuser 
Beitragsersteller
 22.06.2024, 10:53

OK wenn ich das richtig verstanden habe muss ich meinen gesamten Code der sich in in der Loop-Funktion befindet in eine Funktion auslagern und die dann mit millis() aufrufen?

stealthuser 
Beitragsersteller
 22.06.2024, 11:28
@jo135

sieht aber aus als wenn ich das Problem jetzt doch so lösen konnte:

unsigned long previousMillis = 0; 
const long interval = 200; 




void loop() {
 unsigned long currentMillis = millis(); 
  if (currentMillis - previousMillis >= interval) { 
    previousMillis = currentMillis; 
    solarpanelcontrol();
  }
}


void solarpanelcontrol()
{
DateTime now = rtc.now();
// Deley-Ausgleich für den Countdown
if (Timer == 0) {
  Timer = Countdown;
  }
if (timeshift < 4)
  {
  timeshift++;
  }
else
  {
 timeshift = 0; 
 Timer--;
  }
Temperatur = rtc.getTemperature();
Temperatur = (float)Temperatur;


//Sonnenrichtungssensoren auslesen
LDR_up = analogRead(A0) + 20; // Sensorkalibrierung
LDR_west = analogRead(A2) + 45;  // Sensorkalibrierung
LDR_east = analogRead(A3); 
LDR_down = analogRead(A3);
Gesamtwert = LDR_up + LDR_west + LDR_east + LDR_down; // Gesamtmenge Licht


if (Helligkeitsglaettung > 0)
  {
  smooth_lumen();
  }
else
  {
  GM_Lumen = round(Gesamtwert / 10)*10;
  }


//Zeitformatierung Countdown
hours = floor(Timer/3600);
minutes = floor(Timer/60-(hours*60));
seconds = floor(Timer-((hours*3600)+(minutes*60)));


//Potiprozent berechnen
Potentiometerwert = analogRead(A6);
Potentiometerdifferenz = Potentiometerwert - Potentiometerminimum;
Potentiometerproz = 50.0 / Potentiometermax * Potentiometerdifferenz;
Potentiometeranz = 100 - (int)Potentiometerproz;
Potentiometeranz = Potentiometeranz + 80;


// Hinweise zur Richtungssteuerung:
 // digitalWrite(RELAISX, HIGH); // LOW = nach Osten HIGH = nach Westen
 // digitalWrite(RELAISZ, LOW); // LOW = nach Oben / HIGH = nach Unten


//  digitalWrite(RELAIS_PowerX, LOW); // LOW = Power On / HIGH = Power off
//  digitalWrite(RELAIS_PowerZ, LOW); //LOW Power On / HIGH = Power off



anemometer(); // Anemometer auswerten


// Wetter- und Lichtabhängiger Algorithmus für die Solarsteuerung
if (now.hour() == 3 && now.minute() == 0 && now.second() == 0) // Zeitpunkt für Korrektur der horizontalen 0-Position
  {
  angel_reset = 1;
  }
if (Temperatur > Mindesttemperatur)
  {
  if (Windmaximum < rpm)
    {
    storm_protection();
    }
  else if(angel >= -30 && angel_reset == 1)
    {
    startpoint_reset();
    }  
  else if (GM_Lumen < Mindesthelligkeit) 
    {// zu wenig Licht - die Anlage soll in die Neutralstellung fahren
    neutral_position();
    }
  else // Nachfuehrung im Normalbetrieb
    {
    solar_move();
    }
  }
// Anzeige für HD44780 2004 LCD (i2c) Display formatieren
show_display();
}

Ich habe dafür eine eigene delay-Routine geschrieben.

Die rufe ich immer auf, wenn ich einen delay() brauche, der nicht verhindert, dass ein interupt "übersehen" wird.

Ich habe die in eine Bibliothek ausgelagert, in denen ich eine ganze Reihe Funktionen parke, damit der Code der eigentlichen Sketches nicht überlagert wird.

void routinen::Delay(unsigned long zeit)
{
    unsigned long time = millis();
    unsigned long diff;
    
    do
    {
        diff = millis() - time;
    } while ( diff < zeit );
}

Lese dir mal den Abschnitt "Yield Function: A Function that Keeps Running While Arduino in a Delay" auf der Seite https://atadiat.com/en/e-yield-function-printable-class-mapping-arrays-useful-arduino-core/ durch. yield() ist ein interessanter Ansatz.

Da ich nicht mit dem Arduino selber, sondern meistens mit den Attinys (84 und 85) arbeite, konnte ich mich bisher davor drücken, mich da einzuarbeiten.

Richtiges "echtes" Timing wird du mit den Erweiterungen der Arduinoumgebung eh nicht hinbekommen, dafür haben die zu viel Ballast dabei, um alles möglichen Konflikte abzufangen.

Wenn du nur einen eigenen Code nutzt, ohne irgendwelche fremden Bibliotheken aus dem Internet, kannst du die meisten Arduino Erweiterungen durch viel schnellerer eigene ersetzen.

Beispiel: Wenn ich weiß, welchen Pin ich ansteuere, nehme ich nicht digitalWrite(), sondern

    //digitalWrite(clockPin, HIGH);
    PORTA |= (1 << _clockPin);

    //digitalWrite(clockPin, LOW);
    PORTA &= ~(1 << _clockPin);

Das setzt voraus, dass du dich beim Programmieren auf den PIN und damit auf den Port festlegst. Mit dem Beispiel oben sparst du für das setzen oder löschen eines Bits über 80% Ausführungszeit und der Code wird deutlich kürzer.

Woher ich das weiß:Hobby