programma met interupt stopt random

Daar ik nieuw ben op dit forum, me even voorstellen.
Bouwjaar 1954; Technische scholing en beroepsmatig Elektro-Mechanica ; basisbegrippen electronica; Arduino ervaring beperkt tot enkele kleinschalige projecten voor modelbouw. Meestal copy/paste en aanpassen naar mijn beoogd doel.
Ook zo te werk gegaan voor onderstaande, originele code was geschreven voor serial output.
Doel van dit project: via vibratiesensor frequentie en/of toerental van een motor meten (afwijking van 60-120 rpm is geen probleem) Arduino Pro Mini, 16*2 lcd en voor de test een drukknop aan pin2 met 10k pull-up.
Voeding: zowel 5V via usb>serial, als 9V op RAW getest
Probleem waarom ik hulp zoek op dit forum: Om een voor mij nog onbekende reden stop het programma op zeker ogenblik. Ik heb daarom ook de millis mee opgenomen in de weergave op de lcd
Als ik pin2 constant laag hou stopt het na 25sec; als ik pin2 constant hoog hou, na 33sec; als ik de drukknop blijf pulsen, dan na 12<>80 sec ; beetje afhankelijk van hoe snel/veel ik puls, maar geen duidelijke lijn in te trekken.
Daar echte random niet bestaat moet het in de code zitten.

Hieronder de code

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// read RPM
volatile int rpmcount = 0;
int rpm = 0;
int Hz = 0 ;
unsigned long lastmillis = 0;


void setup() {

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor (0,0);
  lcd.print ("Starting");

  attachInterrupt(0, rpm_engine, FALLING);//interrupt zero (0) is on pin two(2).
}



void loop() {

  if (millis() - lastmillis == 1000) { /*Update every one second, this will be equal to reading frequency (Hz).*/

    detachInterrupt(0);    //Disable interrupt when calculating


    rpm = rpmcount * 60;  //* Convert frecuency to RPM,
    Hz = rpmcount ;

    lcd.clear () ;
    lcd.setCursor(0, 0); // set the cursor to column 0, line 0
    lcd.print ("RPM:");
    lcd.setCursor(6, 0); // set the cursor to column 6, line 0
    lcd.print((rpm));

    lcd.setCursor(0, 1); // set the cursor to column 0, line 1
    lcd.print ("Hz:");
    lcd.setCursor(6, 1); // set the cursor to column 6, line 1
    lcd.print((Hz));
    lcd.setCursor(10, 1); // set the cursor to column 10, line 1
    lcd.print(millis() / 1000);

    rpmcount = 0; // Restart the RPM counter
    lastmillis = millis(); // Uptade lasmillis
    attachInterrupt(0, rpm_engine, FALLING); //enable interrupt
  }
}


void rpm_engine() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmcount++;
}

Een paar dingen: A) heb je een pullup Weerstand naar vcc hangen? B) daar de getallen niet negatief kunnen worden zou ik ze veranderen in uint32_t C) hoeveel toeren draait het geheel? D) krijg je een mooie pulse? E) hoe weet je of je niet midden in een interrupt detached? F) ik zou testen op > 1000 ms niet gelijk aan G) je kan dat hele detachen en attachen in de loop weglaten.

Beste Nico, met schaamrood op de wangen bekennen dat ik uw oplossing tot mijn probleem gevonden heb in een onderwerp op dit forum (snelheid en afstand meten). Als ik naar de vraagsteller zijn code keek was deze quasi gelijk aan deze die ik ook had gevonden (en gecopieerd) op het net. Ik zet hieronder UW, door mij aangepaste, code als werkende oplossing

Antwoorden op uw vragen:
A) ja naar VCC
C) Max 83Hz voor een dieselmotor en 120Hz voor de vibratie van een trilwals
D) zelfs zonder puls (constant hoog) liep hij vast (33sec)
E) zonder puls ook
F) 1000ms = Hz = eenvoudig om te rekenen

Daar ik nog niet weet waarom het vastliep, zelfs zonder puls laat ik het onderwerp nog even open staan voor ik het markeer als opgelost.
Hieronder de werkende code

// Opent de bibliotheek voor de display.
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

#define MEASURE_TIME	1000		// measure every second

unsigned long triggerTijd;		// testen voor elke MEASURE_TIME

volatile unsigned int puls = 0; // 
unsigned long rpm = 0L;
unsigned long Hz = 0L;


void setup() {

  lcd.begin(16, 2);                   // Stelt de LCD in 16 kolommen en 2 rijen.
  attachInterrupt(0, rpm_as, FALLING);	// vallende puls als trigger op interupt 0 = pin 2
  triggerTijd = millis() + MEASURE_TIME;// start de timer
}

void loop() {

  if (millis() > triggerTijd) {

    rpm 		= puls * 60;// bereken het aaltal RPM per minuut
    Hz                  = puls;    //puls / sec = Hz


    lcd.clear();                   // Maak de display leeg.
    lcd.setCursor(0, 0); // Zet de cursor op de gewenste plaats.
    lcd.print("RPM:");
    lcd.setCursor(6, 0);
    lcd.print(rpm);           // Schrijf de variabele "rpm".
    lcd.setCursor(0, 1);
    lcd.print("Hz:");
    lcd.setCursor(6, 1);
    lcd.print(Hz);            // schrijf de variable Hz.

    // reset de pulsteller
    puls = 0;
    triggerTijd = millis() + MEASURE_TIME;// start de timer
  }
}

// wordt aangeroepen bij elke trigger

void rpm_as() {
  puls++;															// verhoog de teller
}

Hoi EX8000, welkom nog.

Als je test op 1000, dan kijk je dus of er precies 1000 frutsels voorbij zijn gekomen.
Stel nou dat je de 1000e frutsel gemist hebt (om wat voor reden dan ook) en je dus bij de 1001e kijkt.
Dan voldoe je dus niet aan de voorwaarde, en gooi je alles weg.
Je zult dan ook nooit meer lastfrutsel updaten, want dat doe je alleen als je aan de eerder genoemde voorwaarde voldaan hebt.
Dus daarom ben je dan hopeloos verloren.

Dat is het punt dat Nico wilde maken.
Het maakt niet uit of het frutsels of millifrutsels zijn.
Ook niet of het frutsels, regendruppels of seconden zijn trouwens.

MAS3 Ik zie in welke richting je antwoord gaat; mijn "lastfrutsel" kan fout en daardoor weg zijn. Nico werkt met millis + 1000 voor de timing

Wel gek dat het steeds na 25 of 33 sec was (bij pin 2 hoog of laag) Maar goed, probleem is opgelost met dank aan u beide en ik zal de raad onthouden Ik markeer de vraag als opgelost.

Das niet helemaal juist. Nico's code heeft dat stukje wel in de sketch die je gevonden hebt staan, maar het werkt net ff anders. Want als je gaat kijken of de verlopen tijd al gelijk is aan millis() plus 1000, dan kun je lang gaan kijken. Want telkens als je kijkt, zijn millis en millis plus 1000 niet gelijk (goh). Daarom wijst Nico eerst een waarde toe aan triggerTijd, en dat word dan gekoppeld aan millis() zoals die er op precies dat moment voor staan.

De controle die er in zit, is of millis() meer is dan triggerTijd. En triggerTijd verandert alleen als die opnieuw word ingesteld (gereset), met het stukje code dat je zag.

Het is niet zo heel vreemd hoor, dat het vrij nauwkeurig te timen is wanneer het fout zal gaan. Je code doet wanneer het knopje is ingedrukt, iets anders als wanneer het niet is ingedrukt. En dus loopt je code de ronde dan in een ander tempo. Zeg maar de ene keer de buitenbaan, en de andere keer de binnenbaan. Op die manier kun je dus beïnvloeden wanneer je uit de pas gaat lopen, maar het staat als een paal boven water dat dat een keer zal gaan gebeuren.