Forum: Compiler & IDEs ATTiny3 Servoimpulse lesen


von hoschi (Gast)


Lesenswert?

Hallo,

ich versuche Servoimpulse aus dem Empfänger auzuwerten.
Ich glaube aber das mein Ablauf zu ungenau ist.
Ich verwende PIN1 INT0 interrupt und den Timer0 /64 clk.
der Tiny13 läuft bei 4,8MHz.

steigende Flanke löst interrupt aus
ich warte mit delay 1000µs (weil es erst dann intressant wird)
schalte den Timer ein
warte bis PIN1 0 wird
schate den Timer ab
übergebe den Wert.

Irgendwie ist das zu ungenau, kann das sein ?

Sollte ich die Impulse generell anders auswerten ?

viele Grüße
Martin

von Karl H. (kbuchegg)


Lesenswert?

hoschi schrieb:

> steigende Flanke löst interrupt aus
> ich warte mit delay 1000µs (weil es erst dann intressant wird)

Vergiss diesen Schritt.
Der delay ist ungefähr 1000µs, aber nicht exakt. Und wenn dir da dann 
auch noch ein Interrupt in der Delayzeit dazwischenfunkt, dann kannst du 
auch gleich eine Sanduhr nehmen um 1 Sekunde abzuwarten.

> schalte den Timer ein
> warte bis PIN1 0 wird
> schate den Timer ab
> übergebe den Wert.
>
> Irgendwie ist das zu ungenau, kann das sein ?
>
> Sollte ich die Impulse generell anders auswerten ?

Starte den Timer, zähle die Overflows und rechne ein wenig.

von hoschi (Gast)


Lesenswert?

aah, dann kann der delay auch wenn er in der interrupt Routine gerufen 
wird vom Interrupt unterbrochen werden weil es eine Funktion ist ?

von Karl H. (kbuchegg)


Lesenswert?

hoschi schrieb:
> aah, dann kann der delay auch wenn er in der interrupt Routine gerufen
> wird vom Interrupt unterbrochen werden weil es eine Funktion ist ?

Solage du nicht selbst mittels sei() die Interrupts freigibst, bist du 
in einer ISR vor weiteren Interrupt Aufrufen geschützt. Trotzdem macht 
man das nicht, dass man in einem Interrupt auf etwas längere Zeit 
wartet.


Ansonsten: Code zeigen hilft.

(Warum denkst du eigentlich, dass das zu ungenau ist)

von Oliver (Gast)


Lesenswert?

Bei clk/64 und 4,8MHz wird die max. 1ms lange Servoposition in 75 
Schritte aufgelöst. Die 1ms Verzögerung zu Anfang braucht es damit dann 
nicht, bei max 2.1ms Servopulslänge zählt der Timer höchstens bis 158. 
Das gibt niemals einen Overflow.

Ob 75 Schritte ausreichend sind, musst du natürlich selber wissen.

Oliver

von hoschi (Gast)


Lesenswert?

ok, vielen Dank für die Tipps.

Dann wäre der neue Programmablauf in etwa so:
INT0 auf steigende Flanke

Bei INT0
Timer0 = 0
Timer einschalten mit passendem Teiler (oder evtl. keinem)
fallende/steigende INT0 Flanke umschalten

bei fallender Flanke :
Timer ausschalten
Überläufe auswerten und endwert übergeben
Überlaufzähler zurückstezen


Bei INT Timer overflow
Überläuf zählen

von hoschi (Gast)


Lesenswert?

Hier mal mein Code versuch.
1
#include "main.h"
2
3
volatile int impuls;
4
volatile int tmr_ov;
5
6
int main (void) {
7
8
9
  GIMSK = (1<<INT0);    // | (1<<PCIE);         //INT0 enable PINchg enable
10
  MCUCR = (1<<ISC00) | (1<<ISC01);             //interrupt auf INT0 steigende Flanke
11
12
13
  DDRB &= ~( 1 << DDB1 );                // Eingänge definieren
14
  DDRB = (1 << DDB2) | (1 << DDB3 ) | (1 << DDB4 );              // Ausgang definieren
15
16
  sei();
17
18
while (1) {
19
20
21
  if (impuls <= 130 && (impuls>=10) ) {    // Werte müssen noch angepasst werden
22
    PORTB |= (1<<PB2);
23
    }
24
    else PORTB &= ~(1<<PB2);         // Pin PB2 und Pin PB3 "low"
25
26
27
  if (impuls >= 170) {            // Werte müssen noch angepasst werden
28
    PORTB |= (1<<PB3);
29
    }
30
    else PORTB &= ~(1<<PB3);         // Pin PB2 und Pin PB3 "low"
31
  }
32
}
33
34
35
36
ISR(INT0_vect) {
37
  TCNT0=0;                // Timer 0 auf 0
38
39
  if  (CS00 == 0) {              
40
      TCCR0B = (1<<CS00);          // Timer 0 Prozessortakt (4,8Mhz) / 1    //timer 0 start
41
    MCUCR = (1<<ISC01);          // interrupt auf INT0 fallende Flanke
42
  }
43
44
45
  if  (CS00 == 1) {  
46
    TCCR0B &= ~(1<<CS00);        // Timer 0 stop
47
      MCUCR = (1<<ISC00) | (1<<ISC01);   // interrupt auf INT0 steigende Flanke
48
49
    impuls=tmr_ov;            // Wert an globale Variable evtl noch Berechnung
50
    tmr_ov=0;              // Overflow Zähler auf null
51
  }
52
53
PORTB ^= ( 1 << PB4 );            // INT und Impulseingang Überwachung  
54
}
55
56
57
ISR(TIM0_OVF_vect) {            // Timer overflow interrupt
58
  tmr_ov++;
59
}

ich habe leider meine Testhardware nicht hier, kann das erst am Abend 
testen. Ich bin auch noch Anfänger bei dem Programmieren, ich bemühe 
mich aber kenne aber nicht viele Tricks.

Jetzt müsste noch in etwa ausgerechnet werden wie hoch die gemessenen 
Werte sein können.

von Karl H. (kbuchegg)


Lesenswert?

hoschi schrieb:

>   if  (CS00 == 0) {

CS00 ist immer 0.
CS00 ist nichts anderes als ein Makro, welches die Bitnummer für das 
'CS00' Bit im Timerkonfiguratinsregister hinter einem Namen kaschiert
1
#define CS00  0
so stehts irgendwo in den Header Files.
Da dem aber so ist, wird dieser Vergleich immer TRUE ergeben.

>   if  (CS00 == 1) {

wohingegen, dieser niemals TRUE sein wird


(OK. Ich verallgemeinere. Auf allen AVR Prozessoren die ich kenne, liegt 
CS00 an der Bitposition 0 und genau genommen muss das nicht unbedingt so 
sein)
1
  if  (CS00 == 0) {              
2
      TCCR0B = (1<<CS00);          // Timer 0 Prozessortakt (4,8Mhz) / 1    //timer 0 start
3
    MCUCR = (1<<ISC01);          // interrupt auf INT0 fallende Flanke
Yep. Genau das ist einer der richtigen Wege.
1
    impuls=tmr_ov;            // Wert an globale Variable evtl noch Berechnung
2
    tmr_ov=0;              // Overflow Zähler auf null
Warum Overflow?
Warum nicht erst mal den Timerstand selber?

von hoschi (Gast)


Lesenswert?

ah, ok danke, du meinst dann warscheinlich eher so:
1
#include "main.h"
2
3
volatile int impuls;
4
volatile int tmr_ov;
5
volatile int flanke;
6
7
int main (void) {
8
9
10
  GIMSK = (1<<INT0);    // | (1<<PCIE);         //INT0 enable PINchg enable
11
  MCUCR = (1<<ISC00) | (1<<ISC01);             //interrupt auf INT0 steigende Flanke
12
13
14
  DDRB &= ~( 1 << DDB1 );                // Eingänge definieren
15
  DDRB = (1 << DDB2) | (1 << DDB3 ) | (1 << DDB4 );              // Ausgang definieren
16
17
  sei();
18
19
while (1) {
20
21
22
  if (impuls <= 130 && (impuls>=10) ) {    // Werte müssen noch angepasst werden
23
    PORTB |= (1<<PB2);
24
    }
25
    else PORTB &= ~(1<<PB2);         // Pin PB2 und Pin PB3 "low"
26
27
28
  if (impuls >= 170) {            // Werte müssen noch angepasst werden
29
    PORTB |= (1<<PB3);
30
    }
31
    else PORTB &= ~(1<<PB3);         // Pin PB2 und Pin PB3 "low"
32
  }
33
}
34
35
ISR(INT0_vect) {
36
  TCNT0=0;                // Timer 0 auf 0
37
38
  if  (flanke == 0) {  
39
    flanke = 1;            
40
    TCCR0B = (1<<CS00);          // Timer 0 Prozessortakt (4,8Mhz) / 1    //timer 0 start
41
    MCUCR = (1<<ISC01);          // interrupt auf INT0 fallende Flanke
42
  }
43
    else {  
44
      flanke = 0;
45
      TCCR0B &= ~(1<<CS00);        // Timer 0 stop
46
      MCUCR = (1<<ISC00) | (1<<ISC01);   // interrupt auf INT0 steigende Flanke
47
48
      impuls=(tmr_ov*256)+TCNT0;      // Wert an globale Variable evtl noch Berechnung
49
      tmr_ov=0;              // Overflow Zähler auf null
50
    }
51
52
PORTB ^= ( 1 << PB4 );            // INT und Impulseingang Überwachung  
53
}
54
55
56
ISR(TIM0_OVF_vect) {            // Timer overflow interrupt
57
  tmr_ov++;
58
}

von Karl H. (kbuchegg)


Lesenswert?

hoschi schrieb:
> ah, ok danke, du meinst dann warscheinlich eher so:

Fast

Welchen Wert wird wohl TCNT0 hier

>
1
>     else {
2
>       flanke = 0;
3
>       TCCR0B &= ~(1<<CS00);        // Timer 0 stop
4
>       MCUCR = (1<<ISC00) | (1<<ISC01);   // interrupt auf INT0 steigende Flanke
5
> 
6
>       impuls=(tmr_ov*256)+TCNT0;      // Wert an globale Variable evtl noch Berechnung
7
>

haben, nachdem du hier

>
1
> ISR(INT0_vect) {
2
>   TCNT0=0;                // Timer 0 auf 0
3
>
den TCNT0 immer auf 0 gesetzt hast :-)

(OK, das ist jetzt ein trivialer Bug. Aber im Grunde: Ja, so sollte das 
fürs erste funktionieren)

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.