Forum: Mikrocontroller und Digitale Elektronik Atmega Maximalwert am ADC für einige Sekunden speichern


von Michael (Gast)


Lesenswert?

Hallo,
ich bräuchte Hilfe bei folgender Aufgabe:

Am ADC liegt eine Spannung an. (Drehzahleingang)

Nun zeigt mir mein Display auch die Drehzahl richtig an. Ich möchte aber 
nun, dass ab einer bestimmten Schwelle mir meine maximale Drehzahl für 
10 Sekunden neben der aktuellen angezeigt wird.

Beispiel:

Motor dreht mit 500 u/min
Anzeige: 500 u/min

Motor hat ein kurzen Peak bis 700 u/min (schwelle liegt bie 650 u/min)
Anzeige: 500u/min max: 700u/min (nach 10 sekunden verfliegen ide 700 
u/min wieder)

scheinbar sitze ich schon etwas zu lange vor dem PC und mir fehlt 
irgendwie der Durchblick. Gibt es eventuell fertige Funktionen die man 
nutzen könnte?

Ich habe neben der Drehzahl noch weitere Werte auf dem Display, weshalb 
eine Schleife für die 10 Sekunden nicht so optimal wäre.

Für Anregungen und Hilfen bin ich wie immer dankbar :)

mfg Michael

von Christoph H. (christoph_b)


Lesenswert?

mit einem Timer??

von Cyblord -. (cyblord)


Lesenswert?

Michael schrieb:

> Nun zeigt mir mein Display auch die Drehzahl richtig an. Ich möchte aber
> nun, dass ab einer bestimmten Schwelle mir meine maximale Drehzahl für
> 10 Sekunden neben der aktuellen angezeigt wird.

Aber das klingt doch schon irgendwie nach Pfusch. Was soll damit 
kaschiert werden? Warum soll eine maximale Drehlzahl erst ab einer 
Schwelle angezeigt werden? Warum lässt du dir nicht einfach die maximale 
Drehzahl der letzten x Messungen dauernd anzeigen? Das wär dann gleitend 
sozuagen.

Abgesehen davon ist das doch trivial zu realisieren, was soll man denn 
da antworten?

von Mitesser (Gast)


Lesenswert?

Michael schrieb:
> Anzeige: 500u/min max: 700u/min (nach 10 sekunden verfliegen ide 700
> u/min wieder)

Und wenn in diesen 10 Sekunden nochmal 660 erreicht werden? Ich vermute 
mal, dann soll die Anzeige das auch anzeigen.
Könnte man Deine Anforderung auch wie folgt formulieren)
"Der höchste Wert innerhalb der letzten 10 Sekunden soll angezeigt 
werden, wenn er unter 650 liegt, ansonsten soll nichts angezeigt 
werden."

von Michael (Gast)


Lesenswert?

Mitesser schrieb:
> Michael schrieb:
>> Anzeige: 500u/min max: 700u/min (nach 10 sekunden verfliegen ide 700
>> u/min wieder)
>
> Und wenn in diesen 10 Sekunden nochmal 660 erreicht werden? Ich vermute
> mal, dann soll die Anzeige das auch anzeigen.
> Könnte man Deine Anforderung auch wie folgt formulieren)
> "Der höchste Wert innerhalb der letzten 10 Sekunden soll angezeigt
> werden, wenn er unter 650 liegt, ansonsten soll nichts angezeigt
> werden."

genau das meinte ich :D habe mich wohl etwas unglücklich ausgedrückt! 
(wenn er über 650 u/min liegt)

von Falk B. (falk)


Lesenswert?

@  Michael (Gast)

>genau das meinte ich :D habe mich wohl etwas unglücklich ausgedrückt!
>(wenn er über 650 u/min liegt)

Ist icht schwer. Man brauch eine Maximalwertspeicherung und ein 
Monoflop in Software. Nehmen wir an, du hast einen Timer, der alle 
500ms deine Messung aufruft. dann ungefähr so.
1
if (timer_500ms) {
2
  a = adc_read();
3
  if (a>a_max)  {
4
    a_max=a;
5
    timeout = 20;
6
  }
7
  if (timeout !=0) {
8
    timeout--;
9
    printf(a_max);
10
  }
11
  printf(a);
12
}

von Mitesser (Gast)


Lesenswert?

Dann teile doch die 10 Sekunden in eine übersichtliche Anzahl von 
Häppchen ein, z.B. ein Array mit 128 16bit-Werten namens Maxima[128].
Welches Element in dem Array aktuell ist, wird durch einen Zähler namens 
Zaehler bestimmt.
Eine Timer-ISR sucht ständig das Maximum dieser 128 Werte und gibt es 
aus, wenn es größer als 650 ist, ansonsten wird ein Leerstring 
ausgegeben.
Den ADC lass einfach im Free Running/Interrupt Modus laufen. (Vorsicht, 
klappt in Realität, nicht im Simulator!) Die ADC-ISR macht:
1
Maxima[Zaehler] = max(Maxima[Zaehler], ADC);
2
++SampleZaehler ;
3
if (SampleZaehler >= SamplesProInterval)
4
{
5
  SampleZaehler = 0;
6
  ++Zaehler;
7
  if (Zaehler >= 128)
8
  {
9
    Zaehler = 0;
10
  }
11
}

von Mitesser (Gast)


Lesenswert?

Das mit der Timer-ISR ist eigentlich unnötig. Das kann man besser in der 
Hauptschleife machen.

Außerdem habe ich vergessen, alte Werte zu löschen:
1
Maxima[Zaehler] = max(Maxima[Zaehler], ADC);
2
++SampleZaehler ;
3
if (SampleZaehler >= SamplesProInterval)
4
{
5
  SampleZaehler = 0;
6
  ++Zaehler;
7
  if (Zaehler >= 128)
8
  {
9
    Zaehler = 0;
10
  }
11
  Maxima[Zaehler] = 0; // <= ganz wichtig!
12
}

von Michael (Gast)


Lesenswert?

dank euch beiden...ich stecke noch am Anfang meiner 
Programmierkenntnisse :) aber ich werde mal versuchen den Code zu 
verstehen....

mit dem Befehl Maxima sucht er automatisch den größten Wert im Array?

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> dank euch beiden...ich stecke noch am Anfang meiner
> Programmierkenntnisse :) aber ich werde mal versuchen den Code zu
> verstehen....
>
> mit dem Befehl Maxima sucht er automatisch den größten Wert im Array?

Nein.
Maxima IST das Array.

Den größten Wert in einem Array suchen sollte dich aber nicht wirklich 
vor programmiertechnische Hindernisse stellen :-)

von Falk B. (falk)


Lesenswert?

@  Michael (Gast)

>mit dem Befehl Maxima sucht er automatisch den größten Wert im Array?

Nein, das ist der Name von einem Array.

von Michael (Gast)


Lesenswert?

ah ok sorry tomaten auf den Augen...klar... :)

Eine frage noch: Wieso muss ich den Array auf 0 setzen? Kann er nicht 
einfach von vorn wieder anfangen zu überschreiben?

von Mitesser (Gast)


Lesenswert?

Weil er sonst bis zum Fahrtende nur die höchste gemessene Drehzahl 
anzeigen würde, weil die Werte nicht überschrieben werden würden. Das 
Setzen auf 0 ist quasi das Überschreiben.
In solchen fällen bietet sich das Oldschool-Konzept "Schreibtischtest" 
an.
Nimm Dir einen Zettel Karopapier (Matheheft), schreibe in die oberste 
Zeile ein paar Phantasiewerte als Inhalt des Arrays, und spiele den 
Algorithmus durch, indem Du in die folgende Zeile die durch die Routine 
geänderten Werte schreibst, usw... Dann wirst Du schnell merken, dass 
wenn das Array voller hoher Werte ist, keine Änderung mehr stattfindet, 
wenn Du nicht das jeweils "älteste" Feld initialisierst, wenn es zum 
aktuellen Feld wird.

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
Noch kein Account? Hier anmelden.