Forum: Mikrocontroller und Digitale Elektronik Zeit für die Programmbearbeitung berechnen.


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe folgendes Problem:
Von der Main-While-Schleife wird immer eine Funktion aufgerufen welche 
Ports steuert und dabei immer wieder einen Taster-Zustand abfragt.
Wenn der Taster gedrückt ist zählt eine Vatiable hoch (statisch). Beim 
ersten "Impuls" (Variable von 0 auf 1) wird ein Delay von 100ms 
ausgeführt um eine Fehlinterpretation vom Prellen zu unterbinden. Beim 
loslassen des Tasters wird ebenfalls ein Delay von 100ms ausgeführt.
...schon klar, 100ms sind viel, aber diese Funktion ist nicht 
zeitkritisch.
Bei einem lange Druck der Taste (z.B. 2 Sekunden) soll eine andere 
Aktion ausgeführt werden (deswegen die hochzählende Variable).

Wie kann ich nun ausrechnen, nach wievielen Funktionsaufrufen die Zeit 
erreicht ist?
Ich kenne die Frequenz, aber wieviele Takte nötig sind um die Funktion 
abzuarbeiten weiß ich nicht. Wie kann man sowas errechnen?

von Wegstaben V. (wegstabenverbuchsler)


Bewertung
3 lesenswert
nicht lesenswert
sowas lässt sich mit delays nicht vernünftig lösen.

Nutze Timer, dann hst du keine Probleme mit deinen Funktionen.

von Peter D. (peda)


Bewertung
1 lesenswert
nicht lesenswert

von Stefan ⛄ F. (stefanus)


Bewertung
2 lesenswert
nicht lesenswert
Zustandsautomaten sind sicher auch hilfreich.

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank, ich habe gerade mal das mit den Timern überflogen. Das 
scheint perfekt für meine Anwendung zu sein.
Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob 
das mit den 100ms ausreichend ist, dann spare ich eine Menge Code (so 
üppig ist der Speicher des ATtiny2313 ja nicht).
Sollte das nicht klappen komme ich darauf zurück.
Da ich das für eine Projektarbeit brauche würde ich gerne so viel wie 
möglich selber schreiben, ansonsten habe ich ein 
Mords-Quellenangabe-Verzeichnis, was nicht unbedingt gut ankommt.
Ob ich einen Code selber geschrieben habe, oder ob der von jemand 
anderes stammt wird ein erfahrener Prüfer sofort sehen 
(Programmier-Stil). Ich werde meinen Code sicher nicht so perfekt hin 
bekommen, wie er hier verfügbar ist, aber wenn er funktioniert (und ich 
am Ende alles auf den ATtiny bekomme) sollte das ganz gut ankommen.

Die Timer scheinen auch von der Performance her gut zu sein, weil das ja 
parallel Hardware-Seitig mitläuft. Code spart man damit allemal.

Vielen Dank :-)

von Tony S. (tooony)


Bewertung
1 lesenswert
nicht lesenswert
- Zustandsautomat
- Handling mit Flag-Variablen
- je nach dem wie ausgelastet dein AVR ist kann man sonst auch auf eine 
millis() Funktion wie beim Arduino zurückgreifen (basierend auf einem 
Timer):  https://github.com/zkemble/millis

von HyperMario (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:

> Wie kann ich nun ausrechnen, nach wievielen Funktionsaufrufen die Zeit
> erreicht ist?

Einen Zahler hochzählen wenn die Taste gedrückt wird
Selbigen auf 0 stellen wenn Sie losgelassen wurde
Den delay an das Ende der Schleife legen

Dann kannst du die unterschiedlichsten Aktionen je nach Zählerstand 
ausführen
Der Delay kann auch beleibig klein werden (dann werden halt der 
Zählerwerte größer)

von Peter D. (peda)


Bewertung
1 lesenswert
nicht lesenswert
Christian R. schrieb:
> Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob
> das mit den 100ms ausreichend ist, dann spare ich eine Menge Code

Da habe ich so meine Zweifel. Ich optimiere meinen Code recht gut.

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:

> Ich optimiere meinen Code recht gut.

Das würde ich für den konkreten Fall der Tastenentprellung bedenkenlos 
unterschreiben. Da ist alles optimiert, was man unter C optimieren kann.

Aber ganz sicher würde das nicht für den allgemeinen Fall deiner Codes 
unterschreiben...

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Irgendwie komme ich nicht weiter.

Ich habe eine Funktion welche immer wieder aufgerufen wird und einen 
übermittelten Wert auf 2 7-Segment-Anzeigen anzeigt.

Nun habe ich zum Testen, ob das mit dem Timer klappt einfach mal 
folgendes versucht:
1
    // Interrups
2
    TCCR1A = ((1<<CS00) | (1<<CS02));    // Counter aktivieren mit einem Prescaler von 1024
3
  
4
    while (1) 
5
    {
6
        if (TCNT1 > 21600) zeigeZeichen(22);
7
        else zeigeZeichen(11);
8
    }
9
    return;

Da der Timer 16 Bit hat und ich mit einer Frequenz von 11.059200 MHz 
takte sollten doch eigentlich 2 Sekunden lang eine "11" angezeuigt 
werden, danach für ca. 4 Sekunden eine "22" und dann wieder von vorne 
beginnend mit der "11" (sofern der Counter wieder bei 0 anfägt).

Es wird aber lediglich die 11 angezeigt und die 22 erscheint niemals.
Was mache ich da falsch?

Ich möchte eigentlich nur den Timer lesen (und ggf. auf 0 setzen) 
können, ohne dass ein Interrupt ausgelöst wird. Alle Pins sind 
anderweitig belegt und ein Interrupt wäre da störend.

Was mache ich falsch?

von Stefan ⛄ F. (stefanus)


Bewertung
1 lesenswert
nicht lesenswert
> TCCR1A = ((1<<CS00) | (1<<CS02));

Fehler: Die Bits CS00 und CS02 befinden sich im Register TCCR1B!

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
JAAAAAA :-)
Genau das war es, nun kappt´s wie es soll.
Vielen Dank :-)

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Christian R. schrieb:
>> Auch vielen Dank für die Tastenentprellung, aber ich schau erst mal ob
>> das mit den 100ms ausreichend ist, dann spare ich eine Menge Code
>
> Da habe ich so meine Zweifel. Ich optimiere meinen Code recht gut.


Du hast zu Recht gezweifelt.
Die 100ms merkte man doch stark, indem die 7-Segment-Anzeige verzögert 
ein-/ausgeschaltet wurde. Das wäre eigentlich nicht so tragisch, aber da 
die beiden Anzeigen abwechselnd angesteuert werden sah es schon 
merkwürdig aus, wenn erst eine ausgeht und 0,1s später die andere.
Wenn ich mit der Zeit runter gegangen bin wurde der optische Aspekt 
besser, aber dafür kam es zu Fehler (prellen).

Nun habe ich eine ganz simple Lösung gefunden. Das geht zum einen so 
schnell, dass man optisch keine Verzögerung in den Anzeigen mehr sehen 
kann und zum anderen ist es auch noch zuverlässiger.
Ich habe einfach sowohl beim Betätigen, wie auch beim Loslassen des 
Tasters eine Schleife laufen lassen, welche so lange läuft bis 250 
Zyklen der gleiche Wert stehen bleibt.
Wenn ein Taster nun also lange prellt läuft die Schleife etwas länger, 
wenn ein Taster gar nicht prellt läuft die Schleife 250 durchläufe, was 
bei 11,059200 MHz ungefähr 23ms sind.

Hier ist meine "Not-Lösung", welche jedoch erstaunlich gut funktioniert.
1
for (uint8_t i=250; i; i--) {
2
    if (PIND & 0x08) i = 250;
3
}
Beim Loslassen habe ich halt
1
if (!(PIND & 0x08))
 benutzt (das ! davor).
Ich habe den Taster (Billist-Ware aus China) nun bestimmt 50x betätigt, 
dabei hatte ich kein einzigen Tastenpreller :-)

von Thomas E. (picalic)


Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:
> wenn ein Taster gar nicht prellt läuft die Schleife 250 durchläufe, was
> bei 11,059200 MHz ungefähr 23ms sind.

Sicher? Das wären ja ca. 1000 Takte pro Schleifendurchlauf - kann ich 
mir bei so einer simplen Schleife irgendwie nicht vorstellen.

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Habe ich falsch gerechnet?
11.059200 MHz / 1024 (Teiler) = 10800 Takte pro Sekunde
250 Durchläufe / 10800 = 0,02315 --> 23 ms

von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Oh, da ist ja der Fehler...
Ich hatte kurz vorher noch mit dem Timer gerechnet, deshalb war ich 
immer noch bei dem Prescaler von 1024.
Das ist hier aber eine "normale" Schleife, und somit:

11059200 Takte / Sekunde (und nicht 10800)
Somit:
250 / 11059200 = 22,6 µs

Nun bin ich doch sehr verwundert, dass die Tastenentprellung so 
überhaupt funktioniert.
...egal es funktioniert und das sogar "Sau schnell" ;-)

Wenn ich mal einen Taster habe der vielleicht länger prellt, dann müsste 
ich auf einen 16 Bit Integer ausweichen und ein paar µs dazu geben.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:
> Die 100ms merkte man doch stark, indem die 7-Segment-Anzeige verzögert
> ein-/ausgeschaltet wurde.

Nun, das Multiplexen von Anzeigen macht man ja auch nicht in der 
Mainloop, sondern im Timerinterrupt. Da kann man dann auch gleich das 
Entprellen mit aufrufen.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Nun, das Multiplexen von Anzeigen macht man ja auch nicht in der
> Mainloop, sondern im Timerinterrupt.

Normalerweise mache ich so viel wie möglich in der Main-Loop. Interrupts 
sollen im Idealfall nur Ereignisse zählen, Flags setzen oder Buffer 
übertragen.

Bei gemultiplexten Anzeigen stimme ich Dir jedoch zu, die flackern sonst 
nämlich sichtbar und das sieht einfach sch*** aus.

von Thomas E. (picalic)


Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:
> 11059200 Takte / Sekunde (und nicht 10800)
> Somit:
> 250 / 11059200 = 22,6 µs

Diese Rechnung stimmt aber auch nicht, denn der Controller braucht 
sicher mehr, als nur einen Takt pro Schleifendurchlauf!

Wie hast Du denn festgestellt, daß die Entprellung funktioniert? Wenn 
Deine Anzeige bei gedrückter Taste etwas anderes anzeigt, als bei 
losgelassener Taste, heißt das ja noch lange nicht, daß sie ggf. beim 
Umschalten nicht ein paar mal hin- und her gesprungen ist. Das Auge ist 
ja recht träge...

: Bearbeitet durch User
von Christian R. (holle)


Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Bei gemultiplexten Anzeigen stimme ich Dir jedoch zu, die flackern sonst
> nämlich sichtbar und das sieht einfach sch*** aus.

Ich habe das Multiplexen in einer Funktion, welche ich aus der Main 
heraus aufrufe.
Da ist keiene Spur von Flackern zu sehen, alles sehr homogen.


Thomas E. schrieb:
> Christian R. schrieb:
>> 11059200 Takte / Sekunde (und nicht 10800)
>> Somit:
>> 250 / 11059200 = 22,6 µs
>
> Diese Rechnung stimmt aber auch nicht, denn der Controller braucht
> sicher mehr, als nur einen Takt pro Schleifendurchlauf!
>
> Wie hast Du denn festgestellt, daß die Entprellung funktioniert? Wenn
> Deine Anzeige bei gedrückter Taste etwas anderes anzeigt, als bei
> losgelassener Taste, heißt das ja noch lange nicht, daß sie ggf. beim
> Umschalten nicht ein paar mal hin- und her gesprungen ist. Das Auge ist
> ja recht träge...

Stimmt, die Schleife braucht auch etwas.

Mit dem Tastendruck habe ich die Anzeige aus-/eingeschaltet. Vorher (mit 
prellen) flackerte diese beim drücken öfters uns blieb dann an oder aus. 
Die hat halt nich einmal aus- oder eingeschaltet, sondern x mal und ist 
dann irgendwo stehen geblieben (an oder aus).
Nun habe ich den Taster ca. 50 mal betätigt und ich hatte weder 
Flackern, noch einen Fehlerhaften wechsel (an <--> aus).

Ich bin noch ein blutiger Anfänger, was die Programmierung von µC 
betrifft, somit bin ich für jeden Tipp (und auch konstruktive Kritik) 
dankbar.

: Bearbeitet durch User
von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:
> Ich habe das Multiplexen in einer Funktion, welche ich aus der Main
> heraus aufrufe.
> Da ist keiene Spur von Flackern zu sehen, alles sehr homogen.

Dann hast du wahrscheinlich das Glück, dass jeder Durchlauf der 
Hauptschleife ungefähr gleich lange dauert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.