Delay tot de waarde veranderd

hoi forumleden,
ik ben nieuw op het forum en nog maar een week of 2 begonnen met Arduino.
na het 1 of ander te hebben gelezen op het forum en me rond gesnuffeld te hebben op google, geraak ik er niet meer uit.

de bedoeling van de loop heb ik ineens bij de sketch geschreven om hier tekst te besparen.
het aan uit van de drukknop, werkt zoals ik wil. en de temp en drukknop worden constant uitgelezen.
als de loop dan in keuze functie van temperatuur zit, blijven de leds knipperen.
met een gewone delay functie lukt dit dus niet.

alvast bedankt, `

`int buttonpin = 2;
int buttonread;
int temppin = A0;
float temp;

int ledG = 11;
int ledR = 12;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
temp *0.048828125;
pinMode(buttonpin, INPUT_PULLUP);
pinMode(ledG, OUTPUT);
pinMode(ledR, OUTPUT);

}

void loop() {
// put your main code here, to run repeatedly:
buttonread = digitalRead(buttonpin);
temp = analogRead(temppin);

Serial.print("knop: ");
Serial.print(buttonread);
Serial.println();
Serial.print("tempertauur: ");
Serial.print(temp);
Serial.print("°C");
Serial.println();
delay(500);

if (buttonread == 0) {// als drukknop gedruk is
buttonread = digitalRead(buttonpin);

        if (temp>= 100) { //als temp>=100
        digitalWrite(ledR, LOW);
        digitalWrite(ledG,HIGH);
        delay(350);
        digitalWrite(ledG,LOW);
        } //de bedoeling is dat ledG 1x aan en daarna terug uit, ter zekerheid ledR gwn uit doen 
        // in de praktijk zal ik de leds vervangen door spoelen, die met een H brug zal bediend worden. 
        // na opdrachten uitgevoerd te hebben wacht tot druknop uit of verandering van temp<=100. 
                    
        else { //als temp<=100 
        digitalWrite( ledG, LOW);
        digitalWrite( ledR, HIGH);
        delay(350);
        digitalWrite( ledR, LOW);
        }// na opdrachten uitgevoerd te hebben wacht tot druknop uit of verandering van temp>=100.
        // de bedoeling is dat ledR 1x aan gaat daarna terug uit 

}
else { // als drukknop niet gedrukt is. doe ledG en ledR uit en wacht tot drukknop is gedrukt
digitalWrite(ledG, LOW);
digitalWrite( ledR, LOW);
}

}``

Kijk hier eens naar: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce, dat is waarschijnlijk jouw probleem.

En je leest ook 2 keer buttonpin in dezelfde iteratie;

buttonread = digitalRead(buttonpin); // <------------------------- Hier
temp = analogRead(temppin);
...
if (buttonread == 0) {// als drukknop gedruk is
buttonread = digitalRead(buttonpin); // <------------------------- En hier

Dat is waarschijnlijk ook niet nodig.

Ik vermoed dat je op een 'finite state machine' gaat uitkomen. In een FSM heb je een aantal stappen (states) en je gaat van stap naar stap afhankelijk van condities. Hieronder een uitgewerkt voorbeeld (niet perfect maar doet waarschijnlijk wat je wilt).

Het programma maakt gebruik van een millis() gebaseerde benadering om de delay() kwijt te raken. Het eenvoudge voorbeeld is dat je een eitje wilt koken. Je gooit het eitje in een pan met kokend water (vergelijk met het hoog maken van een pin) en kijkt op de klok wat de tijd is; vervolgens kijk je af en toe op de klok om te zien of de (bv) drie minuten verstreken zijn en als dat het geval is haal je je eitje uit het water (vergelijk met het laag maken van een pin).

Eerst moet je de stappen bepalen; ik kwam op het volgende uit, je kunt dit aan het begin van je sketch toevoegen.

enum STATES
{
  WAIT_BUTTON,          // wacht tot knop wordt ingedrukt
  DEBOUNCE,             // ontdender of kijk of knop is los gelaten
  CHECK_TEMPERATURE,    // kijk of actie moet worden ondernomen gebaseerd op temperatuur
  LEDG,                 // doe actie voor groene led
  LEDR,                 // doe actie voor rode led
};

Een enum is een type (net zoals int, char etc) met een aantal gedefinieerde waardes (die je zelf bepaalt). Je kunt dan later een variabele van dat type deklareren (zie de sm() functie hieronder,

Vervolgens kun je de basis opzetten voor de FSM

void sm()
{
  // finite statemachine stap
  static STATES currentState = WAIT_BUTTON;

  // lees knop en temperatuur
  buttonread = digitalRead(buttonpin);
  temp = analogRead(temppin);

  switch (currentState)
  {
    case WAIT_BUTTON:
      break;
    case DEBOUNCE:
      break;
    case CHECK_TEMPERATURE:
      break;
    case LEDG:
      break;
    case LEDR:
      break;
  }
}

Je kunt nu de stappen invullen; in WAIT_BUTTON kijk je of de knop ingedrukt is

    case WAIT_BUTTON:
      ledG_executed = false;
      ledR_executed = false;

      // als de knop ingedrukt is
      if (buttonread == LOW)
      {
        // onthoud de tijd dat de knop ingedrukt werd
        startTime = millis();
        // ga naar de volgende stap
        currentState = DEBOUNCE;
        Serial.println("Naar DEBOUNCE");
      }
      break;

Je hebt een variabele startTime nodig om bij te houden wanneer de knop werd ingedrukt. En twee variabelen die aangeven of LEDG / LEDR uitgevoerd zijn.

In DEBOUNCE kijk je of de knop dendert of losgeaten is of dat de knop stabiel is voor een gegeven tijd. Afhankelijk daarvan ga je terug naar WAIT_BUTTON of ga je verder naar CHECK_TEMPERATURE.

    case DEBOUNCE:
      // als de knop losgelaten werd of denderde
      if (buttonread == HIGH)
      {
        // terug naar vorige stap
        currentState = WAIT_BUTTON;
        Serial.println("Terug naar WAIT_BUTTON");
      }
      else
      {
        // als de knop stabiel is voor 100 ms
        if (millis() - startTime >= 100)
        {
          // naar de volgende stap
          currentState = CHECK_TEMPERATURE;
          Serial.println("Naar CHECK_TEMPERATURE");
        }
      }
      break;

In CHECK_TEMPERATURE kun je nu bepalen wat uitgevoerd moet worden gabaseerd op temperatuur en of het al uitgevoerd was.

    case CHECK_TEMPERATURE:
      // onthoud de start tijd voor gebruik met de led
      startTime = millis();

      // volgende stap afhankelijk van temperatuur
      if (temp >= 100)
      {
        // indien de groene led niet gedaan was
        if (ledG_executed == false)
        {
          currentState = LEDG;
          Serial.println("Naar LEDG");
          // houd bij wat uitgevoerd was
          ledG_executed = true;
          ledR_executed = false;
        }
      }
      else
      {
        // indien de rode led niet gedaan was
        if (ledR_executed == false)
        {
          currentState = LEDR;
          Serial.println("Naar LEDR");
          // houd bij wat uitgevoerd was
          ledR_executed = true;
          ledG_executed = false;
        }
      }
      break;

Eerst onthoud je de start tijd voor de tijd dat de puls moet duren; dezelfde variabele wordt gebruikt als voor de ontdendering. Vervolgens vergelijk je de temperatuur en verandert de stap als de code voor de temperatuur nog niet iutgevoerd was.

De laatste twee stappen zijn voor de respectievelijke temperatuur acties.

    case LEDG:
      // ter zekerheid ledR gwn uit doen
      digitalWrite(ledR, LOW);
      // ledG aan
      digitalWrite(ledG, HIGH);
      // als de gegeven tijd verlopen is
      if (millis() - startTime >= 350)
      {
        // ledG uitt
        digitalWrite(ledG, LOW);
        // terug naar debounce
        currentState = DEBOUNCE;
        Serial.println("LEDG compleet, terug naar DEBOUNCE");
      }
      break;
    case LEDR:
      // ter zekerheid ledG gwn uit doen
      digitalWrite(ledG, LOW);
      // ledR aan
      digitalWrite(ledR, HIGH);
      // als de gegeven tijd verlopen is
      if (millis() - startTime >= 350)
      {
        // ledR uit
        digitalWrite(ledR, LOW);
        // terug naar debounce
        currentState = DEBOUNCE;
        Serial.println("LEDR compleet, terug naar DEBOUNCE");
      }
      break;

Dit gedeelte zal terug gaan naar de DEBOUNCE stap

  1. Als de knop in de tussentijd los gelaten was zal de DEBOUNCE stap terug gaan naar de WAIT_BUTTON stap.
  2. Als de knop nog steeds ingedrukt is, zal if (millis() - startTime >= 100) naar true evalueren en het programma gaat weer naar de CHECK_TEMPERATURE stap.

De extra variabelen die in de sm() functie gebruikt worden zijn als volgst gedeklareerd in de sm() functie zelf

void sm()
{
  // finite statemachine stap
  static STATES currentState = WAIT_BUTTON;
  // variabele om start tijd te onthouden
  static uint32_t startTime;
  // variabelen om te onthouden of LEDG en LED uitgevoerd zijn
  static bool ledG_executed = false;
  static bool ledR_executed = false;
  
}

Alle variabelen zijn static

  1. Dit houdt in dat de inhoud niet verloren gaat als de loop() functie eindigt (hetzelfde effect als wanneer je ze als globale variabelen zou deklarerern).
  2. Ze zijn lokaal voor de functie; dit maakt dat de functie volledig op zichzelf kan staan (met uitzondering van de variabelen die al in je originele program gebruikt zijn) en dat er geen risico is dat een andere functie ze kan veranderen.

Je roept sm() aan vanuit loop()

void loop()
{
  sm();
}

Kijk of je dit begrijpt en aan de gang kunt krijgen.

Er zit een foutje in je originele programma; de regel temp * 0.048828125; doet helemaal niets, je gooit het resultaat of de berekening weg.

klopt, het was dubbel aan het lezen. heb ze verwijderd.
de debounce funktie te samen met een switch case zoals [sterretje] het zegt.
ik ga eerst wat meer info opzoeken het het dan eens uitproberen.

bedankt

snap de bedoeling wel wat je wil uitleggen, maar het voorbeeld van de ei dringt me niet zo direct door.
zoals eerder vermeld wil ik in de praktijk spoelen gebruiken en dit met een H-brug de DC voeding controleren bij het wisselen van de polen.

yeps klopt, in me eerdere sketch had ik int temp en had dit gewoon overgenomen. in de huidige sketch is het float.

bedankt voor de hulp, ik zal het eens uitproberen met jouw sketch.
ik laat het resultaat weten.

Je eet nooit een gekookt eitje ? :smiley:

Stap Eitje Arduino
1 doe eitje in de pan digitalWrite(pin, HIGH)
2 kijk op klok startTime = millis()
3 doe wat anders bv. lees seriele poort
4 kijk op klok currentTime = millis()
5 als tijd nog niet verstreken is, terug naar 3 if (currentTime - startTime < x)
6 haal eitje uit water digitalWrite(pin, LOW)

hehehe, jawel mag het wel graag.
maar het gaat over de millis() , alijd nuttig natuurlijk.
eerder heb ik het wat anders nodig. de bedoeling is na het uit te voeren opdracht (1x uitvoeren) en daarna op je plaats blijven wachten tot er een waarde veranderd (temp of button) in mijn hele sketch. de millis is goed om het te doen juist in dat ene opdracht zelf vermoed ik, of ik ben er nog niet helemaal weg mee :slight_smile: .

in ieder geval is het opgelost, heb heel de nacht tot morgenvroeg zitten proberen en puzzellen. :sleepy:

bedankt aan iedereen voor het meedenken!! :+1:

nu werkt de sketch zoals gewenst. en het ziet er als volgt uit :

int buttonpin = 2;
int buttonread;
int temppin = A0;
float temp;

int ledG = 11;
int ledR = 12;
int A;
int B;
int C;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(buttonpin, INPUT_PULLUP);
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
    
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonread = digitalRead(buttonpin);
  temp = analogRead(temppin);
  
  Serial.print("knop: ");
  Serial.print(buttonread);
  Serial.println();
  Serial.print("tempertauur: ");
  Serial.print(temp);
  Serial.print("°C");
  Serial.println();
  Serial.print(A);
  Serial.println();
  Serial.print("B=");
  Serial.print(B);
  Serial.println();
  Serial.print("C=");
  Serial.print(C);
  Serial.println();
  delay(250);

                    

  



if (buttonread == 0) {
 C = 0;
  
 
            if (temp <= 100 && A == 0) {
            digitalWrite(ledG, LOW);
            digitalWrite(ledR,HIGH);
            delay(50);
            digitalWrite(ledR,LOW);                     

            A++;           
            }

            if (A==1 && temp < 100){ B = 0; }
            
            
            if (temp >= 100 && B == 0) { 
            digitalWrite( ledR, LOW);
            digitalWrite( ledG, HIGH);
            delay(50);
            digitalWrite( ledG, LOW);          
            
            B++; 
            }

            if (B==1 && temp > 100) {A = 0;} 
  
}
   if (buttonread == 1) {
    if(C == 1) {
  digitalWrite(ledG, LOW);
  digitalWrite( ledR, LOW);   

    A = 0;
    B = 0;
    C++;
 
    }
   

   if(buttonread == 1 && C == 1){} 
   

  
}
}

op deze manier blijft het 'infinity' waardoor de temp en button blijft controleren.
en telkens bij een if aftakking kan ik het opdracht 1 x laten uitvoeren (of meerdere indien gewenst). na het uitgevoerd te hebben een controle uitvoeren met het ABC meegeef systeem(kan je volgen op monitor) en vervolgens de doorgang verwijzen naar een eind loze loop. die komt er terug uit indien een van de waardes veranderd.
je kan ook in de eind loze loop zelf diverse opdrachten laten uitvoeren, want je sketch is 'infinity' en blijft lopen.
de delay tijd bij de opdracht zelf heb ik nodig omdat me installatie niet spanningsloos mag vallen tijdens de handeling zelf. die mag niet halverwege blijven.

en om het algemeen nogmaals te laten luiden:
de AND, OR, OFF poorten gebruiken bied in de meeste gevallen de oplossing.
we vergeten het te vaak!!