so...hab mir einen Zähler so vorgestellt ! void Counter_REAR() { detachInterrupt(5); T_rear=pulseIn(5, HIGH)+pulseIn(rear_axle, LOW,10000); attachInterrupt(5,Counter_REAR,FALLING); } vorher in der void Setup() attachInterrupt(3,Counter_REAR,FALLING); ob falling oder rising ist in dem Fall eher sekundär, würde ich sagen! bin ich da schon am richtigen Weg ?! bei Pulslänge mit mehr als 10ms wird inf0 ausgegeben...
Waren wir uns nicht schon mal (in einem anderen Thread) darüber einig, dass pulsIn gelinde gesagt 'scheisse' ist?
Karl Heinz schrieb: > Waren wir uns nicht schon mal (in einem anderen Thread) darüber einig, > dass pulsIn gelinde gesagt 'scheisse' ist? jup...sind uns nun einig! trotzdem bitte noch mal: void Counter_L_F() { detachInterrupt(3); int counter_pulse_l_f=0; boolean pulse_l_f; if (pulse_l_f==HIGH) { counter_pulse_l_f++; } if (counter_pulse_l_f==150) { counter_pulse_l_f=0; T_l_f=micros(); } attachInterrupt(3,Counter_L_F,RISING); } dachte mir inzwischen, dass ich das vl so löse, dass ich nen Counter hochzählen lasse und dann mittels micros() die Zeit ausgeben lasse, die bis dahin vergangen ist ! jetzt fehlt mir nur noch ein Ansatz, wie ich mittels Interrupt diese Messung auslöse, das erst bei ner gewissen Frequenz...aber so funktioniert das nicht ...der Compiler gibt aber keinen Fehler aus....der ZEITFAKTOR fehlt mir noch da drin! das allein reicht nicht...wenn es überhaupt funktioniert ---> attachInterrupt(3,Counter_L_F,150*RISING);
1 | test.c: In function 'Counter_L_F': |
2 | test.c:3: warning: implicit declaration of function 'detachInterrupt' |
3 | test.c:5: error: 'boolean' undeclared (first use in this function) |
4 | test.c:5: error: (Each undeclared identifier is reported only once |
5 | test.c:5: error: for each function it appears in.) |
6 | test.c:5: error: expected ';' before 'pulse_l_f' |
7 | test.c:6: error: 'pulse_l_f' undeclared (first use in this function) |
8 | test.c:6: error: 'HIGH' undeclared (first use in this function) |
9 | test.c:13: error: 'T_l_f' undeclared (first use in this function) |
10 | test.c:13: warning: implicit declaration of function 'micros' |
11 | test.c:15: warning: implicit declaration of function 'attachInterrupt' |
12 | test.c:15: error: 'RISING' undeclared (first use in this function) |
IDE? Target? Includes! Kommentare!
:
Bearbeitet durch User
Peter Dannegger schrieb: > IDE? > Target? > Includes! > Kommentare! Als Arduino-Programmierer sieht man sofort, wofür das ist: IDE - Arduino-Software Target - ein Arduino-Board Includes - automatisch eingebundene Arduino Core-Libraries Kommentare - bei dem Scheiß, den er da als Code zusammenschreibt, ist eigentlich jeder Kommentar überflüssig. Vielleicht sollte er erstmal grob skizzieren, was er machen möchte. Sein Ziel ist ja wahrscheinlich nicht nur "schreibe ein möglichst irrsinniges Programm, das fehlerfrei kompiliert werden kann", sondern er möchte wohl irgendwas mehr oder weniger sinnvoll ablaufendes programmieren. Bei Ansicht des Tohuwabohu-Arduino-Codes fällt mir nur beim besten Willen nicht ein, was das sinnvolles sein könnte. Aber vielleicht kann er das ja nochmal genauer erklären.
Jürgen S. schrieb: > Kommentare - bei dem Scheiß, den er da als Code zusammenschreibt, ist > eigentlich jeder Kommentar überflüssig. Kommentare sind für einen selber da, um auch später noch zu verstehen, was man mal hingeschrieben hat. Sie können aber auch sofort aufzeigen, daß man sich vorher keine Gedanken über die Funktion gemacht hat. Sie sind sozusagen eine erste Gütekontrolle. Wer meint, ganz ohne Konzept einfach so drauflos schreiben zu können, wird nicht weit kommen.
Peter Dannegger schrieb: > Kommentare sind für einen selber da, um auch später noch zu verstehen, > was man mal hingeschrieben hat. OK, ich weiß nicht, was sich der TO dabei gedacht hat, als er seinen Code schrieb. Aber ich kommentiere seinen Code mal wie folgt:
1 | // Wie ich Arduino-Code schreibe, der NICHTS macht
|
2 | void Counter_L_F() // ich mache mal eine Interrupt-Behandlungsroutine |
3 | {
|
4 | detachInterrupt(3); // Interrupt-Behandlung? Weg damit! |
5 | int counter_pulse_l_f=0; // Setze counter_pulse_l_f auf null |
6 | boolean pulse_l_f; // Deklariere pulse_l_f mit einem unbestimmten Zufallswert |
7 | if (pulse_l_f==HIGH) // Wenn dieser unbestimmte Zufallswert HIGH ist |
8 | {
|
9 | counter_pulse_l_f++; // erhöhe counter_pulse_l_f um 1 |
10 | }
|
11 | // Jetzt ist also counter_pulse_l_f entweder 0 oder 1
|
12 | if (counter_pulse_l_f==150) // Prüfe, ob counter_pulse_l_f auf magische Weise 150 geworden ist? |
13 | {
|
14 | counter_pulse_l_f=0; // in dem Fall setze den auf magische Weise erhöhten Wert wieder auf 0 |
15 | T_l_f=micros(); // und lies den Stand des Mikrosekunden-Timers aus |
16 | }
|
17 | attachInterrupt(3,Counter_L_F,RISING); // Interrupt-Behandlung? Warum habe ich die oben weggehauen? Her damit! |
18 | // Aufgabe erfolgreich gelöst: Der Code verbraucht Rechenzeit und macht: NICHTS!
|
19 | }
|
Mit Kommentaren dran wird's irgendwie auch nicht besser als es ohne schon ist. Wobei ich natürlich nicht weiß, was der TO als Kommentar zu seinem Code geschrieben hätte.
> boolean pulse_l_f; // Deklariere pulse_l_f mit einem unbestimmten Zufallswert > if (pulse_l_f==HIGH) // Wenn dieser unbestimmte Zufallswert HIGH ist Och neee. Im Ernst jetzt?
...es ist schade, dass man eigentlich sogar teilweise FRECHE Kommentare hier erhält! zu meiner Verteidigung, wenn ich schon auf einer Anklagebank sitzen soll, ich hab vorher NIE mit Mikrocontrollern gearbeitet und teilweise ist die Schreiblogik nicht so ganz zu verstehen für mich...ist so....und da kann ich versuchen, was ich will! FAKT IST: ich muss 3 Drehzahlen messen ohne die Loop zu belasten (ohne wird nicht gehen, das ist klar) also, ich bin da auf mich allein gestellt und erhoffte hier ein paar Vorschläge, keinen SENF (...dank denjenigen, die kommentieren, dass mein Code Senf ist) ich hab leider nur mehr 3 Timer (16bit) zur Verfügung und benötige 4?!?! ISR(TIMER3_OVF_vect) //für das linke vordere Rad { Measure_l_f_result++; if (Measure_l_f_result==50) { Measure_l_f=TCNT3; //übergeben vom Counter an Measure_l_f TCNT3=0; //Rücksetzen des Counters und der Variable....entspricht etwa CTC-Einstellung Measure_l_f_result=0; } } vorher definier ich den Timer/Counter so -> TCNT3=0; //Drehzahl-Counter L_F Startwert TCCR3A=0; //zuerst Register A und B auf Standard-Werte setzen TCCR3B=0; TIMSK3|=(1<<TOIE3); //wie arbeitet Interrupt-> Timer Overflow TCCR3B|=(1<<CS32)|(1<<CS31)|(1<<CS30); //steigende Flanke wird gezählt bin ich da immer noch auf dem Holzweg? Bitte, wenn geht, einfach nur dann kommentieren, wenn es ohne "sinnloses Auskotzen" der Meinung geht
:
Bearbeitet durch User
Rene Trattner schrieb: > ...es ist schade, dass man eigentlich sogar teilweise FRECHE Kommentare > hier erhält! Tja, falls Du es nicht wusstest: Ein Forum ist kein Wunschkonzert! Und wenn Du Dir die Frechheit herausnimmst, völlig unkommentierten Quellcode zu posten, der absolut nichts macht, außer mit 0 und 1 zu hantieren und auf 150 zu prüfen und damit Rechenzeit sinnlos zu verbraten, dann kann es Dir tatsächlich passieren, dass Dir jemand mal passende Kommentare dazu schreibt. Noch dazu, wo Du nicht mal wenigstens grob beschreibst, was der Code eigentlich machen soll. > FAKT IST: ich muss 3 Drehzahlen messen ohne die Loop zu belasten (ohne > wird nicht gehen, das ist klar) OK, also "Drehzahlmessung". Drehzahl ist "Umdrehungen pro Zeit", d.h. Du mußt jeweils die Umdrehungen und die Zeit erfassen. Die Umdrehungen erfasst Du offenbar an einem Input-Pin, an dem periodisch HIGH und LOW "Impulse" geliefert werden. Das kann man mit einer Interrupt-Routine erfassen. Also setzt Du z.B. in der setup-Funktion einen Interrupt auf, der entweder auf steigende (RISING) oder fallende (FALLING) Flanke einen Interrupt erzeugt. Zum Beispiel auf steigende Flanke wie von Dir oben vorgeschlagen:
1 | void setup() |
2 | {
|
3 | // ...
|
4 | attachInterrupt(3,Counter_L_F,RISING); |
5 | // ...
|
6 | }
|
Zur Interrupt-Behandlung brauchst Du eine Interrupt-Behandlungsroutine. Variablen, die sowohl innerhalb der Interruptroutine als auch im sonstigen Programm gelesen und/oder gesetzt werden sollen, müssen zwingend mit den Zusatz "volatile" deklariert sein. Um Impulse zu zählen und die Zeit zu berücksichtigen, brauchst Du zwei Variablen: Die eine zählt die Anzahl der Impulse hoch, die andere merkt sich die Zeit. Für eine hohe zeitliche Auflösung am besten den Stand des micros() Timers. So dass Deine Variablendeklaration und Interrupt-Behandlungsroutine so aussehen:
1 | volatile unsigned int counter_ISR; |
2 | volatile unsigned long timer_ISR; |
3 | |
4 | void Counter_L_F() |
5 | {
|
6 | counter_ISR++; // Impulse zählen |
7 | timer_ISR=micros(); // Zeit merken |
8 | }
|
Fertig ist der Code für die Interruptbehandlung: Umdrehungen und Zeit. Immer nachdem die Interruptbehandlung gelaufen ist, ist die Zählvariable um 1 höher als vorher und in der Variablen "timer_ISR" ist der Zeitpunkt vermerkt, wann diese letzte Impulszählung erfolgt ist. Wobei dies Code für relativ langsame Drehzahlen bis einige hundert Umdrehungen pro Minute ist. In Sonderfällen wie "extrem hohe Drehzahlen" zusammen mit "Drehzahlauswertung nur alle paar tausend Impulse" kann die Zeiterfassung auch weggelassen werden, weil es dann bei der späteren Drehzahlberechnung kaum einen Unterschied macht, ob die Drehzahl nun aus 4711 oder 4712 Impulsen berechnet wird. Soweit klar? Jetzt fehlt dann nur noch der passende Code in der loop-Funktion und fertig ist die Drehzahlmessung. P.S.: Du müßtest dringend die BASICS der Programmierung lernen. So wie Du Dich oben damit blamiert hast, eine Variable auf 0 oder 1 zu setzen, um diese danach mit einer if-Bedingungen auf 150 zu prüfen, fehlen Dir absolut die Grundkenntnisse, um irgendwas sinnvoll zu programmieren. Und Interruptprogrammierung ist eher schon ein Thema für Fortgeschrittene.
VIELEN DANK!!! das war sehr verständlich! ich glaub, damit krieg ich es hin!! und blamieren ....ich will es ja kapieren.....blamieren würde ich mich, wenn ich behaupten würde, dass ich es kapier...das habe ich aber nie!!! danke rechtschön erstmal!!
Rene Trattner schrieb: > das war sehr verständlich! > > ich glaub, damit krieg ich es hin!! Ich lese zwar die Worte, aber glauben kann ich das nicht. Denn eine völlig saubere Auswertung der Drehzahl in der loop ist etwas komplizierter/aufwändiger als das bisschen, was die Interruptbehandlungsroutine macht und erfordert ein absolut sauberes Zusammenspiel mit den "volatile" Variablen. Und zwar sowohl, wenn die Auswertung "pro Umdrehung" bzw. "möglichst schnell" oder auch "in gleichen Zeitabständen von z.B. 1x pro Sekunde" stattfinden soll. Also im Zweifelsfall nochmal drübergucken lassen oder nachfragen, bevor Du Dir irgendwas zusammenbastelst, das dann nur "fast immer" funktioniert und Dir manchmal gewaltige "Ausreißer" als Drehzahlwerte zurückliefert.
Rene Trattner schrieb: > ich muss 3 Drehzahlen messen ohne die Loop zu belasten Im einfachsten Fall nimmt man dazu 3 externe Interrupts und einen freilaufenden Timer. Man muß allerdings zuerst mal die Meßgrößen festlegen (min, max, Auflösung, Meßdauer). Dann setzt man den Timer so, daß er bei min noch nicht überläuft. Reicht dann die Auflösung nicht, kann man den Timer auf 24 oder 32 Bit erweitern. Beitrag "AVR Timer mit 32 Bit" Und sage endlich mal, um welches Target es geht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.