Hallo, Im Tutorial über den Watchdog finde ich leider nur, daß er einen Totalreset auslöst - oder habe ich da eine Möglichkeit übersehen? Mein Problem: Eine Schaltung zur Auswertung von Meßwerten soll gegen Sensorausfall abgesichert werden. Wenn z.B. der High-Zustand an einem Sensor länger als eine Sekunde dauert, dann sind die gezählten Counts wertlos und das Zählen kann abgebrochen werden. Es sollte dann aber das Programm zum nächsten Sensor springen - und nicht etwa von vorn beginnen. Ich wollte nicht gern in die Zählschleife eine zusätzliche Abfrage nach einem Grenzwert intgerieren, weil das Zeit kostet und die Zahl der "Nutz"-counts mindert. Es wäre schön, wenn man dem WD sagen könnte: nach 1 sec abbrechen und zu einen anderen Programmpunkt springen. Aber das geht wohl nicht, oder? Vor Timer-Interrupts wollte ich mich gern drücken, weil ich zuwenig davon verstehe und mein Programm zu einem größeren Programm gehört, dessen Interruptmamagement ich vielleicht mit einem unpassendes cli(); störe. Viele Grüße Egon
Egon Müller schrieb: > Hallo, > > Im Tutorial über den Watchdog finde ich leider nur, daß er einen > Totalreset auslöst - oder habe ich da eine Möglichkeit übersehen? Nein. > Vor Timer-Interrupts wollte ich mich gern drücken, weil ich zuwenig > davon verstehe und mein Programm zu einem größeren Programm gehört, > dessen Interruptmamagement ich vielleicht mit einem unpassendes cli(); > störe. Na das is dann natürlich ein Argument... Ich würd sagen, Timer bzw. ein Timer im Capture-Modus wär dein Ding.
Sven P. schrieb: >> Im Tutorial über den Watchdog finde ich leider nur, daß er einen >> Totalreset auslöst - oder habe ich da eine Möglichkeit übersehen? > Nein. Hängt vom konkreten AVR ab. Bei neueren Modellen kann der Watchdog auch einfach nur einen Interrupt auslösen. Ob das allerdings im konkreten Fall irgendwie besser ist, als ein normaler Timer-Interrupt, wage ich zu bezweifeln.
Hallo Sven Leider hat input capture an meinem ATmega16 nur einen einzigen Eingang (ICP 0 Port D6), deshalb hatte ich früher über spezielle IC's die Sensoreingänge reihum auf Port D6 schalten müssen. Die derzeitige Schaltung nach dem Motto "ein Seensor-ein Port" läßt daher kein input capture zu. Gruß Egon
> > Hängt vom konkreten AVR ab. Bei neueren Modellen kann der Watchdog auch > einfach nur einen Interrupt auslösen. > Mein Testboard enthält einen ATmega644p - ob der das kann? [ich habe das Manual nicht - müßte es erst downloaden] Gruß Egon > > Ob das allerdings im konkreten Fall irgendwie besser ist, als ein > normaler Timer-Interrupt, wage ich zu bezweifeln. Meine Sorge ist, die anderen Interrupts nicht zu stören
Egon Müller schrieb: > Die derzeitige Schaltung nach dem Motto "ein Seensor-ein Port" läßt > daher kein input capture zu. Eine Timeout-Funktionalität auf Basis eines Timers bräuchte auch kein Input-Capture. > Ich wollte nicht gern in die Zählschleife eine zusätzliche Abfrage nach > einem Grenzwert intgerieren, weil das Zeit kostet und die Zahl der > "Nutz"-counts mindert. Du müsstest nur zusätzlich eine Variable testen (z.B. auf Null). Das braucht bloß eine Hand voll Cycles. Würde das wirklich nennenswert zu Buche schlagen?
> müßte es erst downloaden
Dann tue das. Du glaubst doch nicht ernsthaft, komplett ohne das
Datenblatt auskommen zu können, oder?
Stefan Ernst schrieb: >> müßte es erst downloaden > > Dann tue das. Du glaubst doch nicht ernsthaft, komplett ohne das > Datenblatt auskommen zu können, oder? Ist auch nicht nötig, das Manual für meinen wichtigsten Prosessor, ATmega 16, habe ich zur Hand, das vom ATmega644 ist auf einem PC, an den ich jetzt nicht herankomme. mfg Egon
Stefan Ernst schrieb: . > > Du müsstest nur zusätzlich eine Variable testen (z.B. auf Null). Das > braucht bloß eine Hand voll Cycles. Würde das wirklich nennenswert zu > Buche schlagen? Diesen Test müßte ich aber doch in die Zählschleife hineinschreiben und dann sind es ebensoviele Takte wie die Sensorabfrage, d.h. die Anzahl der "geernteten" Counts halbiert sich? Vielleicht sollte ich es doch mal mit einem zählergesteuerten Interrupt versuchen und zusehen, ob das übrige Programm noch funktioniert. Gruß Egon
Nicht probieren, sondern wissen! Ohne Systemüberblick gibt's früher oder später Probleme. Zeig doch mal die Routine, die die Counts "erntet". Da läßt sich doch was verbessern!
Egon Müller schrieb: > Diesen Test müßte ich aber doch in die Zählschleife hineinschreiben und > dann sind es ebensoviele Takte wie die Sensorabfrage, d.h. die Anzahl > der "geernteten" Counts halbiert sich? Was genau macht denn diese Zählschleife? Zählen so lange ein Portpin einen bestimmten Pegel hat? Dann gäbe es noch folgende Variante: Zwischen Sensor und Portpin einen Widerstand machen. Der Timer-Interrupt setzt den Portpin auf Ausgang und den entgegengesetzten Pegel und erzwingt somit einen Abbruch der Zählschleife. Zusätzlich wird ein Flag gesetzt, an dem du dann nach der Zählschleife erkennen kannst, dass die Schleife abgebrochen wurde.
Eddy Current schrieb: > Nicht probieren, sondern wissen! Ohne Systemüberblick gibt's früher oder > später Probleme. > > Zeig doch mal die Routine, die die Counts "erntet". Da läßt sich doch > was verbessern! Ist zunächst als while-Schleife realisiert, weil ich z.Zt. noch danebensitze und die Sensorfunktion beobachten kann. Es funktioniert die nackte Abfrage: while ((PIND & 128)) (high = high + 1); }; //end of for Ich müßte also noch eine Abfrage unterbringen, ob high < limit ist, um aus der Schleife herauszukommen. In Basic würde man ohne Unlustgefühle "goto" verwenden. Ich glaube inzwischen, daß sich ein Interrupt doch besser macht. @hi Stefan Wäre sicher eine Möglichkeit. Aber: wenn ich nun doch auf einen Interrupt setze, komme ich dann nicht ohnehin aus der Schleife heraus? Mir ist bloß nach der Tutoriallektüre nicht ganz klar, wohin das Programm aus der ISR springt. Ich würde innerhalb der ISR der Variablen "high" einen Wert zuweisen und dann zu dem Statement unmittelbar nach der while-Schleife springen wollen. Geht das? Viele Grüße Egon
Egon Müller schrieb: > Es funktioniert die nackte Abfrage: > while ((PIND & 128)) > (high = high + 1); > }; //end of for Du könntest zb einen Timer als Zähler benutzen. Dadurch kriegst du in der Schleife ein paar Takte frei um die Abbruchbedingung zu testen
Wenn der Zähler beim inkremenentieren null erreicht, ist er übergelaufen: Timeout, oder so: if (++high == 100) // Count and check timeout goto Timeout; Je nach Datentyp von 'high' kann bei Übertrag vom low-Byte zum high-Byte (16 Bit) für einen Count ein anderes Timing entstehen. Wenn 'high' nur ein Byte ist, paßt alles. Oder sehe ich da den inner Loop einer verschachtelten Schleife?
Egon Müller schrieb: > Wäre sicher eine Möglichkeit. Aber: wenn ich nun doch auf einen > Interrupt setze, komme ich dann nicht ohnehin aus der Schleife heraus? Nein, nicht dauerhaft. > Mir ist bloß nach der Tutoriallektüre nicht ganz klar, wohin das > Programm aus der ISR springt. Das Programm springt genau an die Stelle zurück, von wo es gekommen ist, also wieder in die Schleife. > Ich würde innerhalb der ISR der Variablen > "high" einen Wert zuweisen und dann zu dem Statement unmittelbar nach > der while-Schleife springen wollen. Geht das? "Gehen" tut praktisch alles irgendwie, aber: Ich möchte dir ja nicht zu nahe treten, aber da du ja anscheinend nicht mal damit vertraut bist, was ein Interrupt überhaupt genau ist und macht, liegt das außerhalb deiner Möglichkeiten. Versuch lieber, das erstmal irgendwie "konventionell" zu lösen.
Egon Müller schrieb:
>
1 | > while ((PIND & 128)) |
2 | > (high = high + 1); |
3 | > }; //end of for |
4 | >
|
Das ist nicht gerade der Brüller. Woher weißt Du, mit welcher Frequenz "high" zählt? Nimm nen Timer, dann weißt Du es und obendrein steigt Deine Auflösung. Z.B.:
1 | while( !(PIND & 1<<PD7)); // warte auf high |
2 | // timer start
|
3 | while( (PIND & 1<<PD7) && !(TIFR & 1<<TOV1)); // warte auf low oder T1 overflow |
4 | // timer stop und auslesen
|
Du kriegst von Atmel kein Geld zurück, wenn Du die Timer nicht benutzt. Peter
Peter Dannegger schrieb: > > Du kriegst von Atmel kein Geld zurück, wenn Du die Timer nicht benutzt. > > > Peter Das ist richtig. Und außerdem sind die Zähler doch sehr bequem. Vielen Dank für Eure Hilfe, ich habe das Problem jetzt mit einem Zähler gelöst. Allerdings gibt es noch eionen Wermutstropfen: Das Auslesen des 16-bit-Zählers funktioniert bei mir einfach nicht. Ich habe zuerst (wie im Manual verlangt), den Low-Teil (TCNT1L) ausgelesen und danach den Rest, das liefert Unsinn. Nur wenn ich den Low-Teil von TCNT1 gar nicht anfasse, dann gibt es stabile und plausible Werte (muß allerdings noch nachgemessen werden). Hier die nicht funktionierende Version: unsigned long highabfrage(void) { unsigned long high = 0; DDRD &= 127; // PORTD7 wird Eingang while ( !(PIND & 1<<PD7)); // warte auf high TCCR1B |= (1<<CS10) | (1<<CS12); // Timerstart mit 1/1024 while ((PIND & 1<<PD7) && !(TIFR1 & 1<<TOV1)); // warte auf // low oder T-overflow TCCR1B = 0; // Timer stop high = TCNT1L + (TCNT1H<<8); // auslesen return (high); } Wenn ich in der vorletzten Zeile den Summanden TCNT1L einfach weglasse, funktioniert es. Nun könnte man zwar den Low-Anteil vernachlässigen, aber unschön ist es doch. Ich bin davon ausgegangen, daß der Timer bei jedem Neustart bei Null beginnt; ihn vorher explizit auf Null zu setzen. hat nichts gebracht. Kann mir vielleicht jemand schreiben, was ich da falsch mache? Viele Grüße Egon
1 | high = TCNT1L + (TCNT1H<<8); |
Bei sowas hast du keine Kontrolle darüber, welches Register nun tatsächlich zuerst gelesen wird. Nimm einfach den üblichen Weg:
1 | high = TCNT1; |
> Ich bin davon ausgegangen, daß der Timer bei jedem Neustart bei Null > beginnt; Nein, du musst ihn schon selber wieder auf Null setzen. Außerdem musst du auch noch das Overflow-Flag wieder löschen. PS: Warum eigentlich long? Der Timer hat nur 16 Bit.
Hat sich erledigt! Ich hatte nicht daran gedacht, daß man bei dem Timer in TIVR1 das Overflow-Bit TOV1 manuell zurücksetzen muß, wenn der Interrupt nicht ausgeführt wird. Nun sieht es besser aus. Also nochmals vielen Dank für Eure freundliche Hilfe! Gruß Egon
Egon Müller schrieb: > Hat sich erledigt! > > Nun sieht es besser aus. > > Gruß > Egon April - April! Nichts funktioniert, der Zähler benimmt sich wie Zufallszahlengenerator! Ich mache einen neuen Thread auf, nebenan, bei gcc, wo ja die Sache mit dem Watchdog eigentlich auch hingehört hätte und unter der passenderen Überschrift "Timer... ". Viele Grüße Egon
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.