Forum: Mikrocontroller und Digitale Elektronik PWM-Signal mit AD-Wandler oder mit Frequenzmesser einlesen?


von Rufus (Gast)


Lesenswert?

Hallo,

ich durchforste schon seit einigen Tagen das Forum, ich lese jedoch nur 
wie man mit verschiedene Arten und Weisen PWM-Signale erzeugt.
Nun meine Frage ist: Wie lese ich ein PWM-Signal am besten ein?

-AD-Wandler ?

oder

-Frequenzmessung ?

Ich nehme gerne jeden TIP an und/oder eventl. ASM-Codes würden mir auch 
sehr weiterhelfen.

MfG
Rufus

von Falk B. (falk)


Lesenswert?

Frequenz- bzw. Periodendauermessung. Die Input Capture Funktion bzw. ein 
extern taktbarer Zähler im uC sind dabei sehr hilfreich.

MFG
Falk

von Rufus (Gast)


Lesenswert?

Hallo Falk,

danke vielmals für die rasche Antwort.

ich werde mal im Datenblatt(ATtiny13) nachstöbern, ob es die Funktion 
gibt.

MfG
Rufus

von Rufus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo an alle,

nun sitze ich schon den ganzen Tag hiervor und komme nicht weiter.

@Falk
Es scheint so, als ob der ATtiny keine Input Capture Funktion hat.

Eine "simple" Frequenzmessung
d.H. Bei der positiven Flanke -> Timer Interrupt = Timer läuft
bei der negativen Flanke -> Timer stop
Der Wert von Timer ist die Periodendauer...

Mit dem Programm von Franzis komme ich nicht weit, da verlaufe ich mich 
irgendwie.
µC=ATtiny13 Takt 1,2MHz
Hänge den Code mit an, dass Programm erzeugt ein Testsignal, den will 
ich aber nicht. Ich konnte es auch nicht entfernen.
Ich verzweifele langsam, brauche hilfe, bitte.

von Falk B. (falk)


Lesenswert?

@ Rufus (Gast)

>Es scheint so, als ob der ATtiny keine Input Capture Funktion hat.

Aber sicher, schau dir mal Timer 1 an, Input Capture Unit.

>d.H. Bei der positiven Flanke -> Timer Interrupt = Timer läuft
>bei der negativen Flanke -> Timer stop
>Der Wert von Timer ist die Periodendauer...

Ja, so macht man das.

>Ich verzweifele langsam, brauche hilfe, bitte.

Tja, was soll ich machen? Das Programm schreiben?

MFG
Falk

von Rufus (Gast)


Lesenswert?

hallo

ich habe hetzt einwenig experementiert, aber leider noch nicht zum Ziel 
gekommen. Ich möchte nicht die Peride messen sondern die Frequenz d.H. 
bei der positiven Flanke soll die Zeit 1sek laufen und nach einer 1sek 
den Zählerinhalt (wieviele positive Flanken) rausgeben. Klappt aber 
nicht.
Hier ist der Code, kann mir einer weiterhelfen?
1
    .include "tn13def.inc"
2
3
    .def   A         = r16
4
    .def   timer     = r17
5
    .def   timer2    = r18
6
    .def   sek       = r19
7
    .def   sicher    = r20
8
    .def   Delay     = r23
9
    .def   Count     = r24
10
11
    ;Port B
12
    .equ   TXD      = 1    ;TXD Senden  PB1
13
    .equ   RXD      = 2    ;RXD Empfang PB2
14
    .equ   Eingang  = 3    ;Messeingang PB3
15
16
17
        rjmp Anfang        ;Springe nach Anfang
18
        .org 0x0003
19
        rjmp TIM0_OVF
20
21
Anfang:
22
        sbi    ddrb,TXD    ;SBI=Setze Bit In DDRB 1
23
        ldi    A,7         ;LDI=Lade Register mit Wert 7
24
        out    TCCR0B,A    ;Start mit positiven Flanke
25
        ldi    A,2         ;LDI=Lade Register mit Wert 2
26
        out    TIMSK0,A    ;Timer Interrupt freigeben
27
        clr    timer       ;r17 löschen
28
        clr    timer2      ;r18 löschen
29
        clr    sek         ;r19 löschen
30
        sei
31
        
32
Schleife:
33
        cpi    sek,1        
34
        rcall  Lesen
35
        in     A,TCNT0
36
        rcall  WrCOM      
37
        rjmp   Schleife
38
39
TIM0_OVF:                  ;Timer Interrupt
40
        in    sicher, SREG ;Statusregister in r20 kopieren
41
        ldi   timer, 6     ;LDI=Lade Register mit Wert 6
42
        out   TCNT0,timer  ;TCNT0 auf 6 setzen 256-6=250 bis Overflow
43
        inc   timer2       ;Registerinhaltinhalt um 1 erhöhen
44
        cpi   timer2,75    ;Vergleich Register mit Wert 75
45
        brlo  TIM0_ende    ;Sprung, wenn kleiner (Vorzeichenlos)
46
        clr   timer2       ;r18 löschen
47
        nop
48
        inc   sek          ;Registerinhaltinhalt um 1 erhöhen
49
TIM0_ende:
50
        out   SREG,sicher  ;r20 in Statusregister kopieren
51
        reti               ;Zurück an die Stelle wo das Interrupt begann

Bitte habt verständnis, bin noch ein Anfänger, deshalb kommentiere ich 
es auch so wie oben.

MfG
Rufus

von spess53 (Gast)


Lesenswert?

Hi

Initialisierung vom Stackpointer vergessen.

MfG Spess

von Rufus (Gast)


Lesenswert?

wie macht man das?

von spess53 (Gast)


Lesenswert?

Hi

Anfang:             ldi r16,Low(RAMEND)
                    out SPL,r16

MfG Spess

von Rufus (Gast)


Lesenswert?

Hi,

danke werde ich gleich mal testen.

MfG
Rufus

von Rufus (Gast)


Lesenswert?

Schade hat immernoch nicht geklappt.

Ergebnis ist immernoch 0 0 0 0 0 ...

Am Eingang ist aber definitiv ein Signal (PWM), messe mit Multimeter 
2,6V.

MfG
Rufus

von Rufus (Gast)


Lesenswert?

Hallo,

meine Frage, wie ich ein PWM-Signal messen muss, hat sich ja bereits 
geklärt. Frequenmessung!!!

Ich habe hier ein ASM-Code der Firma Franzis was im Lernpaket dabei war.
1
;Frequenz.asm, Frequenzmessung an PB4
2
3
    .include "tn13def.inc"
4
5
    .def   A      = r16
6
    .def   timer  = r17
7
    .def   timer2 = r18
8
    .def   sek    = r19
9
    .def   sicher = r20
10
    .def   freqlow   = r21
11
    .def   freqhigh  = r22
12
    .def   Delay  = r23
13
    .def   Count  = r24
14
15
    ;Port B
16
    .equ   TXD    = 1
17
    .equ   RXD    = 2
18
19
20
        rjmp Anfang
21
        .org 0x0003 
22
        rjmp TIM0_OVF    ;Timer0 Overflow 
23
Anfang:
24
        sbi    ddrb,TXD    
25
        sbi    ddrb,3    
26
        ldi    A,3        ;Start mit Vorteiler / 64
27
        out    TCCR0B,A
28
        ldi    A,2
29
        out    TIMSK0,A     ;Timer Interrupt freigeben
30
Schleife:
31
        clr    timer2
32
        clr    sek
33
        clr    freqlow
34
        clr    freqhigh
35
        sei                ;Interrupt freigeben   
36
Z1:     sbic   pinb,4        
37
        rjmp   Z2
38
        sbi    portb,3     ;Testsignal
39
        cpi    sek,1
40
        brsh   Z4
41
        rjmp   Z1
42
Z2:     sbis   pinb,4
43
        rjmp   Z3
44
        cbi    portb,3     ;Testsignal
45
        cpi    sek,1
46
        brsh   Z4
47
        rjmp   Z2
48
Z3:     inc    freqlow
49
        brne   Z4
50
        inc    freqhigh
51
Z4:     cpi    sek,1
52
        brlo   Z1
53
Z5:     cli                ;Interrupt sperren
54
        mov    A,freqhigh
55
        rcall  WrCOM
56
        mov    A,freqlow
57
        rcall  WrCOM
58
        rjmp   Schleife
59
60
61
TIM0_OVF:                  ;Timer Interrupt
62
        in    sicher, SREG 
63
        ldi   timer, 6 
64
        out   TCNT0,timer  ;250 bis Overflow
65
        inc   timer2
66
        cpi   timer2,75
67
        brlo  TIM0_ende
68
        clr   timer2
69
        inc   sek
70
TIM0_ende:
71
        out   SREG,sicher
72
        reti
73
74
RdCOM:  sbis  pinb,RXD  ;Empfangen
75
        rjmp  RdCOM
76
        ldi   Delay,58  
77
D1:     dec   Delay
78
        brne  D1
79
        ldi   A,0
80
        ldi   Count,8
81
L1:     lsr   A
82
        sbic  pinb,RXD
83
        ori   A,128
84
        ldi   Delay, 38  
85
D2:     dec   Delay
86
        brne  D2
87
        dec   Count
88
        brne  L1
89
        ldi   Delay, 38
90
D3:     dec   Delay
91
        brne  D3
92
        com   A
93
        ret
94
95
WrCOM:  sbi   portb,TXD  ;Senden
96
        ldi   Delay,38 
97
D4:     dec   Delay
98
        brne  D4
99
        ldi   Count,8
100
L2:     sbrc  A,0
101
        rjmp  OFF
102
        rjmp  ON
103
ON:     sbi   portb,TXD
104
        rjmp  BitD
105
OFF:    cbi   portb,TXD
106
        rjmp  BitD
107
BitD:   ldi   Delay,38  
108
D5:     dec   Delay
109
        brne  D5
110
        lsr   A
111
        dec   Count
112
        brne  L2
113
        cbi   PORTB,TXD
114
        ldi   Delay,38  
115
D6:     dec   Delay
116
        brne  D6
117
        ret

Ich hänge nun mein PWM-Signal an PB4 und bekomme: 0 123 0 123 0 122 0 
123 0 124 0 123 0 123.... in sekunden Takt werden nun jeweils zwei Bytes 
empfangen: 0 und 122 oder 123 oder 124. Die gemessene Anzahl der Impulse 
ist damit 0*256+123=123, d.h. die Frequenz beträgt 123Hz.
Wenn ich das PWM-Signal mit einem Multimeter messe habe ich 2.6V
Das Signal kommt übrigens aus einem ADXL202 (Beschleunigungssensor), 
wenn ich es kippe (links/rechts) messe ich +/-0.2V als 2.4-2.8V.
Nur am Terminal bleibt der wert immer gleich: 0 123 0 123 0 122 0 123...
Warum?

Noch eine Frage:
Der Timer wird vom Vorteiler mit 1,2MHz/64 getaktet. Er zählt 250 Takte 
bis zum Überlauf. Dazu wird das Timer-Register jedes Mal mit einem neuen 
Startwert von 6 geladen. Daraus ergibt sich eine Interruptfrequenz von 
75Hz (1200000/64/250=75). Nach jeweils 75 Interrupts wird der 
Sekundenzähler erhöht. Warum entspricht 75Hz eine 1sekunde?

von spess53 (Gast)


Lesenswert?

Hi

Bevor du weitermachst solltest du erst mal deine serielle Verbindung 
testen. Interner RC-Oszillator + Software-UART scheint mir etwas gewagt. 
Hast du schon mal getestet, ob du wirklich die Zeichen empfängst, die an 
WRcom übergeben werden. Bevor das nicht sicher ist, brauchst di garnicht 
weitermachen.

MfG Spess

P.S. Der Tip mit dem Stackpointer war Quatsch. Ich war irgendwie auf 
ATTiny2313.

von Rufus (Gast)


Lesenswert?

hallo Spess,

zu deiner Frage, ja, es scheint zu funzen. Habe diverse Programme 
getestet mit schreiben und lesen. Es ist auf 9600Baud eingestellt. Erst 
bei 115200 Baud kommt es zu einzelnen Übertragungsfehlern. Bei einer 
Bitlänge von knapp 9 µs reicht also die zeitliche Auflösung des 
ASM-Programms nicht mehr aus.
Hast du dennoch Antworten auf meine Fragen?

MfG
Rufus

von Rufus (Gast)


Lesenswert?

@ Falk Brunner (falk)

>Aber sicher, schau dir mal Timer 1 an, Input Capture Unit.

Der ATtiny besitzt nur den Timer/Counter0 und kein Timer 1 und somit 
auch kein Input Capture Unit.


Die Antwort kommt nur so spät, weil ich seit 1,5 Wochen mich 
ausschließlich nur damit beschäftige und so allmählich werden einige 
Sachen auch klar.
Aber trotzdem danke für deine Hilfe.

@all

Ich komme trotz des vieeeeeelen vielen lesens noch nicht mit der Messung 
des PWM-Signals nicht ganz klar. Ich habe eine Erklärung, aber ob es 
richtig ist weiß ich nicht. Und Zwar: Der Code s.oben macht eine 
Frequenzmessung und gibt mir die Frequenz via SW-UART auf den Terminal 
wieder. Wie ich bereits geschrieben hatte, messe ich mit einem 
Multimeter Spannungen zwischen 2.4-2,8V je nach Schräglage des ADXL 
(PWM-OUT). Selbstverständlich bleibt die Periodendauer die Selbe, weil 
es ja keine Impulsmessung ist, sondern eine Frequenz bzw. Periodendauer 
Messung ist.
Sprich , wenn T1(Impuls) + T2(Pause) = Periodendauer ist, muss ich 
wissen wie sich T1 zu T2 verändert um Werte zu erfassen mit denen ich 
weiter arbeiten kann. RICHTIG?

Wäre echt sehr Nett , wenn mir das jemand bestätigen oder verneinen 
(falls nicht richtig) könnte.

MfG Rufus

von Rufus (Gast)


Lesenswert?

>Der ATtiny besitzt nur den Timer/Counter0 und kein Timer 1 und somit
>auch kein Input Capture Unit.

sry, meine natürlich den ATtiny13

von Ulrich (Gast)


Lesenswert?

Die Frequenzmessung bringt wirklich nicht viel. Man muß die Zeiten für 
high und low level einzeln messen. Im pronzip sollte das aber sehr 
ähnlicher der Frequenzmessung gehen.

von Rufus (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

danke Ulrich, zu dieser Erkenntnis bin nun auch gekommen.

Hab den ADXL202 jetzt mal mit einen Oszi ausgelesen, siehe Anhang.
In einigen Treads über PWM und Beschleunigungssensoren hatte ich 
gelesen, dass sich T1 verändert und T2 würde gleich bleiben, demnach 
müsste sich bei jeder Abtastung die F ändern. Natürlich ist das aber 
nicht richtig, weil T2 verhält sich propotional zu T1, d.H. F bleibt 
immer gleich.

Ich habe nun wirklich (ohne Hilfestellung) meinen allerersten 100% aus 
eignem Gedankengang entstandenen ASM-Prog geklimmpert :)
Viele Spezis werden es wahrscheinlich mit Ironie nehmen, aber ich bin 
dennoch glücklich, weil ich allmählich die Syntax begriffen habe :)

So nun zum ASM-Code:
Es wird bestimmt auch eleganter und einfacher gehen, aber mit dem 
Simulator sieht es schon ganz gut aus. Bei einer +Pulsbreite von ~4ms 
muss ich natürlich noch ein TIMER_OVF mit Einfügen und später etwas 
umrechnen.
Vielleicht kann mir jemand einpaar Tips geben wie ich den ASM-Code 
verfeinern kann. Danke
1
;Pulsbreitenmessung (vereinfacht)
2
3
    .include "tn13def.inc"
4
5
    .def  A        = r16
6
    .def  timer    = r17
7
8
Beginn:
9
    ldi    A,0            ;TCNT0 leeren
10
    out    TCNT0,A
11
loopa:
12
    sbis   pinb,4         ;PB4 abfragen
13
    rjmp   loopa          ;wiederholen
14
    rjmp   Tgo            ;weiter, wenn Signal da ist
15
Tgo:
16
    ldi    A,1            ;Timer aktiveren ohne Vorteiler
17
    out    TCCR0B,A
18
loopb:
19
    sbis   pinb,4         ;PB4 abfragen
20
    rjmp   Tstop          ;Sprung, wenn kein Signal
21
    rjmp   loopb          ;Abfrage wiederholen
22
Tstop:
23
    ldi    A,0            ;Timer stoppen
24
    out    TCCR0B,A
25
    clr    timer           
26
    in     timer,TCNT0    ;Timerwert auslesen zur
27
                          ;Weiterverarbeitung
28
    rjmp  Beginn
Für jeder Art Tips bin ich sehr dankbar.

MfG Rufus

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.