LØST RPM måler del 2

Hej

Her er en udløber af forrige topic (RPM måling).

Jeg vil have en funktion der sender Serial.println når tiden mellem 2 interupts overstiger x-sekunder.

Jeg er kommet frem til følgende sketch, hvor tiden millis() rigtig nok går i gang, men mit problem er at jeg ikke kan få et nyt interupt til at nulstille Millis(), funktionen skal nemlig ikke sende Serial.println hvis der kommer nyt interupt inderfor x-sekunder. Og så skal Serial.println kun sendes en gang, mens tiden er oversteget x-sekunder:

volatile int state = LOW;
int unsigned long starttid;
int unsigned long sluttid;
int unsigned long lastsluttid;
int laststate = 0;
int PAUSE = 0;
int lastmillis = 0;

void setup()
{
  Serial.begin(9600);

  digitalWrite(3, HIGH);
  attachInterrupt(1, autoslut, FALLING);
}

void loop()
{

  if (state==LOW)

    starttid = millis();

  {


    if (millis() > 5000)
     {
      Serial.println(millis());

      Serial.println("Tiden er udløbet");
      
    }

    
    starttid = 0;

  }
}
void autoslut()
{
  state = !state;
}

LYDFANGER

Davs,

jeg er ikke helt klar hvor(for) vi har to interrupts? Du havde en (et fast antal) interrupt per omdrejning.

Kode mæssigt vil din interrupt bare tælle op, eller hejse et flag (afhængigt hvor vigtigt det er at ikke miste en interrupt)

Din loop() skal bare notere millis() hver gang den ser flaget hejst (eller tælleren større end nul), og hvis flaget ikke er hejst (tællere står på 0) så skal den sammenlignene det gemte millis med det nuværende. Er forskellen større end xtusind millis så har noget stået stille. Du kan så sende din Serial.

Din loop kode kan så behandle flaget/tælleren mhp på at udskrive din RPM.

Hej igen

Så det du siger er :

Jeg kan godt bruge flere millis() på samme interupts? (mener at have læst at det ikke kunne lade sig gøre)

Vh
LYDFANGER

Jeg siger millis() og interrupts som du har attachet til, har intet med hindanden at gøre - udover det du programerer dem til.

(På et dybere plan har de - millis() er en tæller der bliver talt op med en hver gang et interrupt der er sat til at køre hver millliskund udløses.)

Hej

Din loop() skal bare notere millis() hver gang den ser flaget hejst (eller tælleren større end nul), og hvis flaget ikke er hejst (tællere står på 0) så skal den sammenlignene det gemte millis med det nuværende. Er forskellen større end xtusind millis så har noget stået stille. Du kan så sende din Serial.

Jeg går ud fra den notere millis() er "gemt" i timeold
Hvordan får jeg den sammenlignet med den nuværende millis()? Det er der mit hoved problem ligger (ud over jeg ikke er særlig logisk tænkende) XD.
Jeg har prøvet med

if (millis()-timeold > 5000)    
 {
Serial.println("tiden er udlobet"); }

....og en masse andre....

if (rpmcount==1) 
    timeold=millis();
      
  else if (rpmcount >= 15) { 
  
    rpm = 30000L/(millis() - timeold)*(rpmcount-1); //


    rpmcount = 0;
{
    Serial.println(rpm);
}
if (millis()-timeold > 5000)    
 {
Serial.println("tiden er udlobet"); }

LYDFANGER

Der er noget galt med dine { } 'e

if (rpmcount==1)          // Hvis vi har drejet mindst et trin
   timeold=millis();      // Så noter aktiviteten
 else                     // ?? dvs hvis vi enten har stået stille eller drejet for hurtigt ??
   if (rpmcount >= 15) {  // hvis der er gåt 15 interrupts
     rpm = 30000L/(millis() - timeold)*(rpmcount-1); // udregn det til rpm.
     rpmcount = 0;        // nulstil for næste 15 tick runde
{                         //??
     Serial.println(rpm);  // udskriv rpm udregningen
}                         // ??
     if (millis()-timeold > 5000)  // skulle været helt udenfor, nu er den del af det 15.e tick
                                   // - test om vi står stille
 {
Serial.println("tiden er udlobet"); }  // skriv vi står stille
                          // mangler et afsluttende } (som så står det forkerte sted...

Jeg har givet nogle hints. Jeg kan også omskrive koden, men den er næsten der. Overvej om if'erne behover være nested eller med else.

yes,yes,yes.

Nu kører det.

Dog er der en lille ting som måske kunne blive bedre: når cykel har stået stille og Unoen har skrevet "Du bruger jo ikke benene", er det som om der er en "tids rest", som unoen regner videre på når pedalerne bliver trådt igen. Er der en metode til at fjerne denne rest, så man undgår at "rpm" bliver for lille, i forhold til det nye tempo i pedalerne. Eller: kan man blokere Serial.println i x-sekunder?

const int UP = 13;
const int DOWN = 12;

volatile int rpm;

unsigned long timeold;
unsigned long timenew;
unsigned long timediff;
volatile byte rpmcount;


const int HURTIG = 10;
const int LANGSOM = 20;
const int PAU =30;
int lastState;
int lasttimediff;
int sidste;

boolean lastbuttonUP = HIGH;          // debounce//
boolean currbuttonUP = HIGH;
boolean lastbuttonDOWN = HIGH;      
boolean currbuttonDOWN = HIGH;

int PushCounter = 0;
int lastPushCounter = 0;
int lastrpm = 0;

void setup()
{
  pinMode(UP, INPUT);
  digitalWrite(UP, HIGH);
  pinMode(DOWN , INPUT);
  digitalWrite(DOWN, HIGH);


  Serial.begin(9600);
  attachInterrupt(0, rpm_fun, RISING); // Interrupt triggers on rising edge; when the sensor turns off.

  digitalWrite(2, HIGH);
  rpmcount = 0;
  rpm = 0;
  timeold = 0;

}
boolean debounceUP(boolean lastUP)              //debounce UP/
{
  boolean currentUP = digitalRead(UP);
  if (lastUP != currentUP)
  {
    delay(50);
    currentUP = digitalRead(UP);
  }
  return currentUP;

}


boolean debounceDOWN(boolean lastDOWN)              //debounce DOWN/
{
  boolean currentDOWN = digitalRead(DOWN);
  if (lastDOWN != currentDOWN)
  {
    delay(50);
    currentDOWN = digitalRead(DOWN);
  }
  return currentDOWN;

} 
void loop()                                            //void loop//
{
  currbuttonUP = debounceUP(lastbuttonUP);                  // up //
  if(lastbuttonUP == HIGH && currbuttonUP == LOW)
  {
    PushCounter++;
    PushCounter = min(PushCounter, 10);
    Serial.print("PROFIL:");
    Serial.println(PushCounter);

  }
  lastbuttonUP = currbuttonUP;



  currbuttonDOWN= debounceDOWN(lastbuttonDOWN);            //DOWN//
  if(lastbuttonDOWN == HIGH && currbuttonDOWN == LOW)
  {
    PushCounter--;
    PushCounter = max(PushCounter, 1);
    Serial.print("PROFIL");
    Serial.println(PushCounter);
  }
  lastbuttonDOWN = currbuttonDOWN;


  if (rpmcount==1) 
    timeold=millis();


  else if (rpmcount >= 15) { 



    rpm = 30000L/(millis() - timeold)*(rpmcount-1);

    rpmcount = 0;
    {
      Serial.println(rpm);
    }


  }

  if ( rpm >= 60 && lastState!=HURTIG)
    if (rpm!=lastrpm) 
    { 
      lastrpm=rpm ;

      switch (PushCounter)
      {
      case 1 : 
        Serial.println("HURTIG 1"); 
        break;
      case 2 : 
        Serial.println("HURTIG 2"); 
        break;
      case 3: 
        Serial.println("HURTIG 3"); 
        break;
      case 4: 
        Serial.println("HURTIG 4"); 
        break;
      case 5: 
        Serial.println("HURTIG 5"); 
        break;
      case 6: 
        Serial.println("HURTIG 6"); 
        break;
      case 7: 
        Serial.println("HURTIG 7"); 
        break;
      case 8: 
        Serial.println("HURTIG 8"); 
        break;
      case 9: 
        Serial.println("HURTIG 9"); 
        break;
      case 10: 
        Serial.println("HURTIG 10"); 
        break;

      }


      lastState = HURTIG;
    }


  if ( rpm <= 59 && lastState!=LANGSOM)
    if (rpm!=lastrpm) 
    { 
      lastrpm=rpm ;
      switch (PushCounter)
      {
      case 1 : 
        Serial.println("LANGSOM 1"); 
        break;
      case 2 : 
        Serial.println("LANGSOM 2"); 
        break;
      case 3: 
        Serial.println("LANGSOM 3"); 
        break;
      case 4: 
        Serial.println("LANGSOM 4"); 
        break;
      case 5: 
        Serial.println("LANGSOM 5"); 
        break;
      case 6: 
        Serial.println("LANGSOM 6"); 
        break;
      case 7: 
        Serial.println("LANGSOM 7"); 
        break;
      case 8: 
        Serial.println("LANGSOM 8"); 
        break;
      case 9: 
        Serial.println("LANGSOM 9"); 
        break;
      case 10: 
        Serial.println("LANGSOM 10"); 
        break;

      }

      lastState = LANGSOM;


    }
  timediff = millis()-timeold;
 
  if (timediff > 10000 && lastState!=PAU)
    if (timediff!=lasttimediff) 
    { 
      lasttimediff=timediff;
      switch (PushCounter)
      {
      case 1 : 
        Serial.println("Du bruger jo ikke benene 1"); 
        break;
      case 2 : 
        Serial.println("Du bruger jo ikke benene 2"); 
        break;
      case 3: 
        Serial.println("Du bruger jo ikke benene 3"); 
        break;
      case 4: 
        Serial.println("Du bruger jo ikke benene 4"); 
        break;
      case 5: 
        Serial.println("Du bruger jo ikke benene 5"); 
        break;
      case 6: 
        Serial.println("Du bruger jo ikke benene 6"); 
        break;
      case 7: 
        Serial.println("Du bruger jo ikke benene 7"); 
        break;
      case 8: 
        Serial.println("Du bruger jo ikke benene 8"); 
        break;
      case 9: 
        Serial.println("Du bruger jo ikke benene 9"); 
        break;
      case 10: 
        Serial.println("Du bruger jo ikke benene 10"); 
        break;

      }

      lastState = PAU;

    }

}
void rpm_fun()
{
  rpmcount++;

}

LYDFANGER

Tja, ja ... hvor tror vi at denne "rest" gemmer sig?

Jeg har ikke helt gennemskuet meningen med Pushcounter, men lige nu er min fornemmelse at du skal nulstille rpmcount ved "lastState = PAU;".

Hvis du ikke vil "undertrykke" Serial.print, så skal du putte noget logik omkring den at den ikke bliver brugt. Det kan f.eks. gøres ved at lave sin egen PrintMig() funktion der laver en test om man mener det, og hvis true så bruge Serial.print og ellers ignorere det.

I øvrigt, der er den lille hage at all de strenge du har med de beskeder bliver gemt i RAM som du kun har en 1700 bytes til rådighed af. Der er måder at putte dem i den ekstra NVram chippen har. Søg efter "freemem" for at få vist hvor meget ledig RAM der er i din sketch når den kører, så ved du om det er nødvendigt.

Jeg korrigerer mig en smule.

Når du skriver Serial.print("Hello") så indholder programmet (der ligger i "flash") 5 bytes med H-E-L-L-O. Før setup() bliver kaldt, sørger Arduinosystemet for at kopiere de 5 bytes til RAM. Selve koden for udskrift siger Print 5 bytes ved RAM-position-x.

Hvis du skriver koden Serial.print(F("hello")); så sker der magi - din RAM forbrug er nu 5 bytes mindre, din kode en smule længre. Nu bliver teksten ikke kopieret til RAM men udskrift koden finder den selv frem i "flash". Dette gælder fra Arduino V1, ikke den (gamle) 0022 version.

Hej hej.

Tak for dit input, jeg vil huske det til senere projekt.
mht. "tidsresten" viser det sig ikke at være et problem i praksis på cyklen. Efter cyklen har stået stille er det altid det samme Serial.println der bliver sendt til pc'en, og praksis kan man ikke se, "pc-filen" bliver startet forfra.

Derfor:

"jeg erklærer hermed problemerne for løst" XD

Endnu engang tak for hjælpen og nye ideer.

LYDFANGER

Det var så lidt ... :wink: Belønning er at vide det blev løst.

Jeg har givet dig et Karma point (ikke fodi det betyder så meget) fordi det er godt du retter i overskriften til LØST.