Go Down

Topic: Millis funktioniert nicht (Read 1 time) previous topic - next topic

maeckes

Hallo!

Hier erst mal der Code:

Code: [Select]

#include <math.h>


//Variablen deklarieren---------------------------------------------------------------------------------------------

long int Impuls=0;                  //Zählt die Anzahl der steigenden Flanken zur Messung der Drehzahl
long vorherigeMillisekunden = 0;    //Millisekunden - Variable für Drehzahl
long int Intervall = 2000;               //Zeit zwischen Drehzahl
int Drehzahl;                       //Drehzahlvar.


//Setup---------------------------------------------------------------------------------------------

void setup()
{  
 
   attachInterrupt(0, Impulszaehler, RISING);  //Wenn an Interrupt 0 (I/0 Eingang 2) steigende Flanke, dann Hilffunktion "Impulszaehler" ausführen
   Serial.begin(9600);    //Serielle Ausgabe initialisieren
}


//Hauptprogramm---------------------------------------------------------------------------------------------

   void loop()
{
 
  unsigned long derzeitigeMillisekunden = millis();
 
  if(derzeitigeMillisekunden - vorherigeMillisekunden >= Intervall) {          //Wenn der Millisekundenzähler - vorherige Millisekunden >= Intervall
   vorherigeMillisekunden = derzeitigeMillisekunden;                          
   Drehzahl = (Impuls/3)*60;                                                   //Drehzahl = (Impulse/2 Sek) * (60s/1min) * (1 Umdrehung / 3 Impulse)
  Serial.println(Drehzahl);
   Impuls=0;                                                                   //Impuls auf 0 setzen
   }
 
//Hilfsfunktionen---------------------------------------------------------------------------------------------
 
}

void Impulszaehler(){      //Hilfsfunktion Impulszählen bei steigender Flanke
 Impuls++;                //Variable Impuls inkrementieren    
}


Gemessen wird mit einem induktiven Sensor eine Drehzahl. Pro Umdrehung gibt es 3 Impulse.
Eigentlich müsste die Drehzahl doch auf Grund der millis-Funktion nur alle 2 Sek ausgegeben werden, richtig?
Die Ausgabe kommt aber dauerhaft!

Wo sitzt der Fehler?

Gruß
Morris

Eisebaer

hi,

also mir gibt das programm alle 2 sekunden einen wert aus. keinen sinnvollen klarerweise, weil ich nichts am pin hängen hab', aber brav alle 2 sekunden...

gruß stefan
nimm abblockkondensatoren!  100nF.  glaub mir, nimm abblockkondensatoren!

maeckes

Komisch - an dem klappts nicht  :smiley-fat:

Eisebaer

hi,

ich hab' winxp und ide 1.05.

klappt denn das blinkwithoutdelay bei Dir? kannst ja eine serielle ausgabe machen statt der led.
und nimm den sensor von pin.

gruß stefan
nimm abblockkondensatoren!  100nF.  glaub mir, nimm abblockkondensatoren!

michael_x

Die etwas unglückliche Stellung des Kommentars
Code: [Select]
//Hilfsfunktionen---------------------------------------------------------------------------------------------
lässt mich raten, dass bei dir im Originalcode die geschweiften Klammern anders sitzen ???

Quote
an dem klappts nicht  :smiley-fat:

ist mir leider etwas unverständlich.

Ich verstehe dein Problem so, dass die Serial.println - Ausgabe nicht alle 2 Sekunden, sondern erheblich häufiger ( "dauerhaft" ) kommt

maeckes


Die etwas unglückliche Stellung des Kommentars
Code: [Select]
//Hilfsfunktionen---------------------------------------------------------------------------------------------
lässt mich raten, dass bei dir im Originalcode die geschweiften Klammern anders sitzen ???


Ne - passt so. Der Kommentar müsste hinter die geschweifte Klammer, aber das tut ja zum Programmablauf nichts zur Sache.


Ich verstehe dein Problem so, dass die Serial.println - Ausgabe nicht alle 2 Sekunden, sondern erheblich häufiger ( "dauerhaft" ) kommt

Korrekt

jurs


Hier erst mal der Code:
...
Wo sitzt der Fehler?


Bei dem geposteten Code erfolgt die Aktualisierung alle 2 Sekunden.
Der Fehler steckt also wohl nicht im geposteten Code.

Wenn das Programm größer ist als was Du gepostet hast und viel mehr RAM-Speicher verbraucht als der von dir gepostete Code, und das Programm aus einem nicht weiter erkennbaren Grund durchdreht, dann steht als Vermutung im Raum, dass Du möglicherweise zu verschwenderisch mit RAM-Speicher umgegangen bist und der Sketch nun mehr RAM benötigen würde als der Controller überhaupt eingebaut hat.

Füge mal diese Funktion in Deinen Code ein:

Code: [Select]

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}


Und lasse Dir an verschiedenen Stellen im Code die Menge des verfügbaren RAM-Speichers anzeigen:
Code: [Select]

Serial.println(freeRam());

Was wird denn da angezeigt?

maeckes

Nein - das Programm, was ich hier gepostet habe, ist 1zu1 das, was auf dem Arduino drauf ist.

Eventuell ein Defekt am Board?

sschultewolter

Welche IDE nutzt du?

In der Arduino IDE sowie Visual Studio 2012 Pro gibt es kein Problem mit der Anzeige.

Kommentier mal im Setup die Zeile vom Interrupt aus.
Keinen technischen Support über PN!

jurs


Nein - das Programm, was ich hier gepostet habe, ist 1zu1 das, was auf dem Arduino drauf ist.

Eventuell ein Defekt am Board?


Welche Arduino-Version verwendest Du?
Welches Arduino-Board verwendest Du?
Verwendest Du eine alternative IDE?
Warum steht in Deinem Code "#include <math.h>" obwohl das in der Arduino-IDE nicht notwendig ist?

Was ist mit diesem Code, an dem ich einige kleine Modifikationen vorgenommen habe, aktualisiert der auch "ständig" und nicht nur alle zwei Sekunden?

Code: [Select]

#include <math.h>


//Variablen deklarieren---------------------------------------------------------------------------------------------

long Impuls=0;                      //Zählt die Anzahl der steigenden Flanken zur Messung der Drehzahl
unsigned long vorherigeMillisekunden = 0;    //Millisekunden - Variable für Drehzahl
#define Intervall 2000              //Zeit zwischen Drehzahl
int Drehzahl;                       //Drehzahlvar.


//Setup---------------------------------------------------------------------------------------------

void setup()

    attachInterrupt(0, Impulszaehler, RISING);  //Wenn an Interrupt 0 (I/0 Eingang 2) steigende Flanke, dann Hilffunktion "Impulszaehler" ausführen
    Serial.begin(9600);    //Serielle Ausgabe initialisieren
}


//Hauptprogramm---------------------------------------------------------------------------------------------

void loop()
{
   unsigned long derzeitigeMillisekunden = millis();
   
   if(derzeitigeMillisekunden - vorherigeMillisekunden >= Intervall) {          //Wenn der Millisekundenzähler - vorherige Millisekunden >= Intervall
    vorherigeMillisekunden = derzeitigeMillisekunden;                           
    Drehzahl = (Impuls/3)*60;                                                   //Drehzahl = (Impulse/2 Sek) * (60s/1min) * (1 Umdrehung / 3 Impulse)
    Serial.println(Drehzahl);
    Impuls=0;                                                                   //Impuls auf 0 setzen
   }
 
//Hilfsfunktionen---------------------------------------------------------------------------------------------
 
}

void Impulszaehler(){      //Hilfsfunktion Impulszählen bei steigender Flanke
  Impuls++;                //Variable Impuls inkrementieren   
}



Serenifly

"long Impuls" sollte auch als volatile deklariert werden. Das wird aber nicht das Problem hier sein.

k4ktus

Testest du das mit dem Geber? Wenn ja welche Drehzahl?

evtl die serial Instanz mal vorm interrupt initialisieren.
my blog and projects:
http://simons-holzvergaser.blogspot.com/

k4ktus

und mal ansagen auf welchen arduino das laufen soll
my blog and projects:
http://simons-holzvergaser.blogspot.com/

rudirabbit

#13
Sep 25, 2013, 06:11 pm Last Edit: Sep 25, 2013, 06:13 pm by rudirabbit Reason: 1
Ist auch nicht das Kernproblem :
Beim Anfassen von "long Impuls" außerhalb der ISR sollten die Interrupt gesperrt werden, nur wenn byte benutzt wird geht es ohne.
Das wurde mir zumindest hier gesagt, wenn ich das richtig verstanden habe.
Arduino UNO,MEGA  Fremdgänger mit dem  Nucleo L152RE   
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

michael_x


Ist auch nicht das Kernproblem :
Beim Anfassen von "long Impuls" außerhalb der ISR sollten die Interrupt gesperrt werden, nur wenn byte benutzt wird geht es ohne.
Das wurde mir zumindest hier gesagt, wenn ich das richtig verstanden habe.

Richtig, und nicht das Kernproblem, auch richtig.
Es muss schon ganz dumm kommen, dass das einen Fehler verursacht:
z.B. genau wenn Impuls gelesen wird, und die Variable den Wert 255 hat, kommt ein Interrupt.
Wenn zuerst das hi Byte gelesen wird und dann das lo, kann statt 255 oder 256 auch eine 0 rauskommen,
wenn zuerst das lo Byte gelesen würde, könnte auch eine 511 rauskommen.

Allerdings muss der Interrupt, der von 255 auf 256 hochzählt, genau den Lesebefehl unterbrechen.
Und dann muss auch einer zufällig hingucken ;)

Wenn die weitere Behandlung von Impuls kritisch ist, schadet es nicht, das durch kurzzeitig geschlossene Interrupts in loop() abzusichern,
aber wenn es nur um eine Testausgabe auf SerialMonitor geht, ist die Wahrscheinlichkeit, dass man dieses Problem je bemerkt, sehr gering.

Go Up