Forum: Mikrocontroller und Digitale Elektronik Time Slot erzeugen - wie am besten


von Steffen (Gast)


Lesenswert?

Hallo
In einem Programm verwende ich einen Timer1 (16Bit) um 10 ms zu erzeugen 
und verwende diese 10ms dann in der ISR:
1
void timer1_init()        // Timer 1, 16 Bit, 8MHz, 10ms
2
  {            // Timer 1 konfigurieren
3
    TCCR1A = (1<<WGM01);      // Auswahl CTC Modus
4
    TCCR1B = (1<<CS01)|(1<<CS00);    // Prescaler auf 64 setzen
5
    OCR1A=1249;        // Wert für 10ms
6
    TIMSK1|=(1<<OCIE1A);      // Interrupt erlauben
7
  }
8
ISR (TIMER1_COMPA_vect)      // Timer 10ms
9
  {  
10
     ...
11
  }
Der 16 Bit Timer ist eigentlich zu schade und brauche ihn für PWM.
Habe dann den 8 Bit Timer0 genommen und mit 1ms laufen lassen. In der 
ISR dann alle 10ms genommen.
1
void timer0_init()          // 8MHz, 8 Bit, 1ms
2
  {              // Timer 0 konfigurieren
3
    TCCR0A = (1<<WGM01);        // Auswahl CTC Modus
4
    TCCR0B = (1<<CS01)|(1<<CS00);      // Prescaler auf 64 setzen
5
    OCR0A=124;          // Wert für 1ms
6
    TIMSK0|=(1<<OCIE0A);        // Interrupt erlauben
7
  }    
8
ISR (TIMER0_COMPA_vect)      // Timer 1ms
9
  {  
10
    millisekunden++;          // Zähler für 10ms
11
    if(millisekunden == 9)
12
      {                  
13
  ……      
14
        
15
  millisekunden = 0;
16
      }
17
  }
Um einen Servo zuschalten brauche ich aber noch andere Zeiten, z.B. 20ms 
und 50ms.
Wie kann ich das aus den 1ms machen. Es wurde Time Slot vorgeschlagen.
Doch wie kann man das vernünftig machen?
LG steffen

von Falk B. (falk)


Lesenswert?

Steffen schrieb:
> Wie kann ich das aus den 1ms machen. Es wurde Time Slot vorgeschlagen.
> Doch wie kann man das vernünftig machen?

Indem man einen passenden Zähler in Software nutzt und nach X 
Durchläufen eine Variable (flag) setzt, welches von einer 
Statemachine in der Hauptschleife ausgewertet wird. Siehe 
Interrupt.

von Steffen (Gast)


Lesenswert?

Wenn ich deine Antwort richtig verstehe, muss man einen passenden Zähler 
z.B. für 20ms zusätzlich in der ISR haben der nach Ablauf der 20ms einen 
Flag setzt.
Beeinfliussen sich beide Zähler nicht in der ISR?

von PittyJ (Gast)


Lesenswert?

In dem Millisekunden ISR noch eine 32-Bit Variable als 
Millisekundentimer mithochzählen.

Alle anderen Sub-Einheiten können dann diese Variable für ihre Timings 
nehmen.

Mache ich seit Jahren so, funktioniert prima.

von Egonwalter M. (heiner1234)


Lesenswert?

Steffen schrieb:
> Wenn ich deine Antwort richtig verstehe, muss man einen passenden Zähler
> z.B. für 20ms zusätzlich in der ISR haben der nach Ablauf der 20ms einen
> Flag setzt.
> Beeinfliussen sich beide Zähler nicht in der ISR?

wenn Du sie unterschiedlich benennst und dementsprechend zurücksetzt - 
kein Problem:
ein Zaehler für die 10ms "countmilli_10"
ein Zaehler für die 20ms "countmilli_20"

in der ISR machst Du es so wie Du es oben schon beschrieben hast - 
fertig

von Teo D. (teoderix)


Lesenswert?

PittyJ schrieb:
> In dem Millisekunden ISR noch eine 32-Bit Variable als
> Millisekundentimer mithochzählen.
>
> Alle anderen Sub-Einheiten können dann diese Variable für ihre Timings
> nehmen.

Gruppiere das und du hast übersichtliche Time-Slots....


Steffen schrieb:
> z.B. für 20ms zusätzlich in der ISR haben der nach Ablauf der 20ms einen
> Flag setzt.
Ja
main(){
if (foo_timer_flag) {
foo_timer_flag=0;
....
}

> Beeinfliussen sich beide Zähler nicht in der ISR?

Natürlich nicht. Wie so sollten sie das auch?

von Steffen (Gast)


Lesenswert?

Da komme ich jetzt nicht so schnell mit. Wenn ich so mache

Steffen schrieb:
> ISR (TIMER0_COMPA_vect)      // Timer 1ms
>   {
>     millisekunden++;          // Zähler für 10ms
>     if(millisekunden == 9)
>       {
>   ……
>
>   millisekunden = 0;
>       }
>   }

und dann weiterzähle ... (ist ja blöd gedacht von mir)
Muss es mal ausprobieren. Hab da wohl einen Knoten im Kopf ....

von Steffen (Gast)


Lesenswert?

PittyJ schrieb:
> In dem Millisekunden ISR noch eine 32-Bit Variable als
> Millisekundentimer mithochzählen.
>
> Alle anderen Sub-Einheiten können dann diese Variable für ihre Timings
> nehmen.
>
> Mache ich seit Jahren so, funktioniert prima.

Sorry, da komme ich nicht ganz mit. Habe einiges programmiert, klappt 
aber nicht wie gewünscht. Hab da wohl noch einen dengfehler drin.
1
ISR (TIMER0_COMPA_vect)    // Timer 1ms
2
  {  
3
    millisekunden++;    // Zähler für 10ms
4
    if(millisekunden == 9)            
5
      {                  
6
        ....
7
        millisekunden = 0;
8
      }
9
    if(millisekunden1 == 20)
10
      (    
11
        flag=1;
12
        ....
13
        millisekunden1 = 0;
14
        flag=0;
15
      }
16
  }
Da ist noch ein Denkfehler drin mit millisekunden1.
Wie meinst du das mit der 32 Bit Variablen?

von Egonwalter M. (heiner1234)


Lesenswert?

Du deklarierst  vier Variable (global, volatile)

Int millisecond_10
Int millisecond_20
flag_milli_10
flag_milli_20

In der ISR lässt Du sie zählen:

millisecond_10++
millisecond_20++

Dann fragst Du in der ISR die 10 und die 20ms ab und setzt jeweils ein 
Flag:

If millisecond_10 == 10 flag_milli_10 = 1
If millisecond_20 == 20 flag_milli_20 = 1

In der main() fragst Du diese beiden flags ab und setzt danach die flags 
und die millisecond zurück (in der Main)

: Bearbeitet durch User
von beo bachta (Gast)


Lesenswert?

Steffen schrieb:
> Da ist noch ein Denkfehler drin mit millisekunden1.
> Wie meinst du das mit der 32 Bit Variablen?

Flags in der ISR setzen, in der Hauptschleife flagbedingte
Sachen ausführen und Flag löschen!
Flags als volatile deklarieren sonst funktioniert das nicht!

von Steffen (Gast)


Lesenswert?

Danke für die Info. Für jede Zeit also einen Zähler und Wert und Flag. 
Das klappt so

von W.S. (Gast)


Lesenswert?

Steffen schrieb:
> In einem Programm verwende ich einen Timer1 (16Bit) um 10 ms zu erzeugen

Könntest du freundlicherweise wenigstens mal andeuten, was für einen 
Controller du zu verwenden gedenkst? Der Hintergrund ist, daß es bei den 
32 bittigen Controller-Sorten von der Cortex-Art einen Timer genau 
dafür bereits in/an der CPU gibt.

W.S.

von beo bachta (Gast)


Lesenswert?

W.S. schrieb:
> Könntest du freundlicherweise wenigstens mal andeuten, was für einen
> Controller du zu verwenden gedenkst?

Könntest du freundlicherweise wenigstens mal versuchen den
Eröffnungs-Post zu lesen? Dort ist unschwer zu erkennen dass
es sich um einen AVR Controller handeln muss.

von Rolf M. (rmagnus)


Lesenswert?

beo bachta schrieb:
> Könntest du freundlicherweise wenigstens mal versuchen den
> Eröffnungs-Post zu lesen? Dort ist unschwer zu erkennen dass
> es sich um einen AVR Controller handeln muss.

Der Code sieht schon sehr nach AVR aus, aber es gehört trotzdem 
eigentlich dazu, dass man zumindest mal erwähnt, worauf das nachher 
laufen soll.

von beo bachta (Gast)


Lesenswert?

Rolf M. schrieb:
> aber es gehört trotzdem
> eigentlich dazu, dass man zumindest mal erwähnt, worauf das nachher
> laufen soll.

Muss man dir auch sagen dass du zum Bäcker gehen musst wenn
du Brot kaufen willst?

von H.Joachim S. (crazyhorse)


Lesenswert?

ist zwar hier kein Problem, sollte man sich aber nicht unbedingt 
angewöhnen:

    if(millisekunden == 9)
      {
        ....
        millisekunden = 0;
      }
Besser:
    if(millisekunden >= 9)
      {
      }

Deckt den Fall == mit ab, und den Fehlerfall (grösser 9, warum auch 
immer) gleich mit. Und bei float ist == auch sehr mit Vorsicht zu 
geniessen.
Es kostet weder Code noch Zeit.

von beo bachta (Gast)


Lesenswert?

H.Joachim S. schrieb:
> Und bei float ist == auch sehr mit Vorsicht zu geniessen.

Das Wort float ist das erste Mal bei dir zu lesen, sonst
keinerlei Vorkommnisse. Wozu also über ungelegte Eier labern?
Vielleicht noch das Thema double einführen?

von Mitleser (Gast)


Lesenswert?

Ist "beo bachta" nicht eines der Moby-Pseudonyme? Der "freundliche" 
Umgangston würde jedenfalls passen.

von Egonwalter M. (heiner1234)


Lesenswert?

Steffen schrieb:
> Hallo
>
> Der 16 Bit Timer ist eigentlich zu schade und brauche ihn für PWM.
>

Na hoffentlich weißt Du wie der Timer für PWM zu parametrieren ist 🤔

Denke da wirst Du wieder Hilfe benötigen

von H.Joachim S. (crazyhorse)


Lesenswert?

beo bachta schrieb:
> Das Wort float ist das erste Mal bei dir zu lesen, sonst
> keinerlei Vorkommnisse. Wozu also über ungelegte Eier labern?

Dann lies einfach noch mal (falls es dir möglich ist verstehend) was ich 
geschrieben habe.

von Rolf M. (rmagnus)


Lesenswert?

H.Joachim S. schrieb:
> Deckt den Fall == mit ab, und den Fehlerfall (grösser 9, warum auch
> immer) gleich mit.

Wobei "deckt" ab in dem Fall heißt: Versteckt einen Fehler. Wenn der 
Wert größer als 9 geworden ist, hat das Programm einen Fehler. Den durch 
>= statt == vertuschen zu wollen, finde ich wenig sinnvoll.

beo bachta schrieb:
> Rolf M. schrieb:
>> aber es gehört trotzdem
>> eigentlich dazu, dass man zumindest mal erwähnt, worauf das nachher
>> laufen soll.
>
> Muss man dir auch sagen dass du zum Bäcker gehen musst wenn
> du Brot kaufen willst?

Nein, aber wenn ich beim Bäcker stehe, mache ich den Mund auf und sage, 
dass ich Brötchen will und warte nicht darauf, dass er das anhand 
irgendwelcher Indizien errät. Das hat auch was mit Höflichkeit zu tun, 
aber das ist dir offenbar fremd.

: Bearbeitet durch User
von Norbert (Gast)


Lesenswert?

Rolf M. schrieb:
> H.Joachim S. schrieb:
>> Deckt den Fall == mit ab, und den Fehlerfall (grösser 9, warum auch
>> immer) gleich mit.
>
> Wobei "deckt" ab in dem Fall heißt: Versteckt einen Fehler. Wenn der
> Wert größer als 9 geworden ist, hat das Programm einen Fehler. Den durch
>>= statt == vertuschen zu wollen, finde ich wenig sinnvoll.

Da vertrete ich seit Jahrzehnten eine andere Auffassung.
Defensive Programmierung. Selbst wenn aufgrund eines physikalischen 
Fehlverhaltens (Strahlung, das böse Auge von Mordor, …) mal ein Bit im 
RAM kippt, läuft das Programm weiter.

Im übrigen
1
millisekunden++;    // Zähler für 10ms
2
if(millisekunden == 9)            
3
{
4
    ...                  
5
    millisekunden = 0;
6
}
zählt der nur neun Millisekunden.

von Wolfgang (Gast)


Lesenswert?

H.Joachim S. schrieb:
> Deckt den Fall == mit ab, und den Fehlerfall (grösser 9, warum auch
> immer) gleich mit. Und bei float ist == auch sehr mit Vorsicht zu
> geniessen.

Wer einen Zähler für Interrupts/Timerdurchläufe als Float implementiert, 
hat ein ganz grundlegendes Problem ;-)

von Norbert (Gast)


Lesenswert?

Wolfgang schrieb:
> H.Joachim S. schrieb:
>> Deckt den Fall == mit ab, und den Fehlerfall (grösser 9, warum auch
>> immer) gleich mit. Und bei float ist == auch sehr mit Vorsicht zu
>> geniessen.
>
> Wer einen Zähler für Interrupts/Timerdurchläufe als Float implementiert,
> hat ein ganz grundlegendes Problem ;-)

Ich kann nicht erkennen das dies impliziert wurde.
Der Satz:
> Und bei float ist == auch sehr mit Vorsicht zu genießen.
ist eine völlig unabhängige/eigenständige Aussage und bezieht sich auf 
Vergleichsoperationen. Außerdem ist die Aussage 100% korrekt.

von Rolf M. (rmagnus)


Lesenswert?

Norbert schrieb:
> Ich kann nicht erkennen das dies impliziert wurde.
> Der Satz:
>> Und bei float ist == auch sehr mit Vorsicht zu genießen.
> ist eine völlig unabhängige/eigenständige Aussage und bezieht sich auf
> Vergleichsoperationen. Außerdem ist die Aussage 100% korrekt.

Ja, aber es gibt keinen Sinn, die Aussage dort einzubringen. Weil == bei 
float problematisch sein kann, soll ich es für int nicht verwenden? Ich 
sehe da den Zusammenhang nicht.

von Falk B. (falk)


Lesenswert?

Wolfgang schrieb:
> Wer einen Zähler für Interrupts/Timerdurchläufe als Float implementiert,
> hat ein ganz grundlegendes Problem ;-)

Frei nach Karl Lagerfeld

Wer einen Zähler mit Float realisiert, hat die Kontrolle über seine ISR 
verloren.

;-)

von Norbert (Gast)


Lesenswert?

Rolf M. schrieb:
> Norbert schrieb:
>> Ich kann nicht erkennen das dies impliziert wurde.
>> Der Satz:
>>> Und bei float ist == auch sehr mit Vorsicht zu genießen.
>> ist eine völlig unabhängige/eigenständige Aussage und bezieht sich auf
>> Vergleichsoperationen. Außerdem ist die Aussage 100% korrekt.
>
> Ja, aber es gibt keinen Sinn, die Aussage dort einzubringen. Weil == bei
> float problematisch sein kann, soll ich es für int nicht verwenden? Ich
> sehe da den Zusammenhang nicht.

Ich glaube ich sehe worauf du hinaus willst. Ich lese das nur etwas 
entspannter.

So wie ich es gelesen habe steht da das man für diese Vergleiche (besser 
Ende Bedingungen) lieber >= und nicht == nehmen sollte.
Aus der Logik heraus, das ein Zähler von 0…9 niemals  andere Werte 
annehmen sollte. Also ist '0' die natürliche untere Grenze und alles >= 
10 die natürliche obere Grenze. Wenn man == nutzt, könnte (im 
zugegebenermaßen extrem seltenen Sonderfall eines physikalischen 
Problems im RAM) der Zähler eine 11,12, und alles weitere bis zum 
Überlauf einnehmen. Bei acht Bit eventuell verschmerzbar, bei 32 Bit 
dauert's schon sehr lange bis er wieder in seinem angestammten Areal 
ankommt. ;-)

Und nur damit kein falscher Eindruck entsteht, als (ganzzahliger) Zähler 
in einer Interrupt-Routine haben Fließkomma Variablen natürlich nichts 
zu suchen. Ich würde mich sehr anstrengen müssen, dafür einen 
Einsatzzweck zu finden.

Die Aussage, so wie ich sie verstanden hatte, war eher:
Wenn man sich daran gewöhnt diese Vergleiche auf Ende mit == 
durchzuführen und man es irgendwann mal (woanders) mit Fließkomma zu tun 
hat, so kann man böse stolpern.

von Egonwalter M. (heiner1234)


Lesenswert?

Falk B. schrieb:
>
>
> Frei nach Karl Lagerfeld
>
> Wer einen Zähler mit Float realisiert, hat die Kontrolle über seine ISR
> verloren.
>
> ;-)

😂👍

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

beo bachta schrieb:
> Könntest du freundlicherweise wenigstens mal versuchen den
> Eröffnungs-Post zu lesen?

Hab ich, aber ich habe dort weder etwas über AVR lesen können, noch bin 
ich Sherlock Holmes. Was bleibt, wäre Rätselraten.

W.S.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Eine Anforderung wurde noch nicht erwähnt:
Wieviel Jitter is denn erlaubt?
Wenn hier ein Servopin gesetzt werden soll, dann müsst der auch in der 
IRQ gesetzt werden, damits wirklich nach 20ms is.
Erst ein Flag setzen und dann in der mainloop checken kann zu Jitetr 
führen und dann zittert der Servo.

W.S. schrieb:
> Hab ich, aber ich habe dort weder etwas über AVR lesen können, noch bin
> ich Sherlock Holmes. Was bleibt, wäre Rätselraten.

Komisch, auf einmal bist du nicht mehr gut in Rätselraten?
Bei meinem ELF Thread haste doch auch munter größten Unsinn 
reininterpretiert aka "Rätselgeraten"
Jetzt bleib doch wenigstens mal konsequent, wenn du sonst schon nur 
Unsinn schreibst.

von H.Joachim S. (crazyhorse)


Lesenswert?

Norbert schrieb:
> Die Aussage, so wie ich sie verstanden hatte, war eher:
> Wenn man sich daran gewöhnt diese Vergleiche auf Ende mit ==
> durchzuführen und man es irgendwann mal (woanders) mit Fließkomma zu tun
> hat, so kann man böse stolpern.

Genauso war es gemeint.

von beo bachta (Gast)


Lesenswert?

W.S. schrieb:
> Hab ich, aber ich habe dort weder etwas über AVR lesen können, noch bin
> ich Sherlock Holmes.

Also im Sich-dumm-Stellen bist du gaaanz gross.

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.