mikrocontroller.net

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


Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

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

MFG
Falk

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
    .include "tn13def.inc"

    .def   A         = r16
    .def   timer     = r17
    .def   timer2    = r18
    .def   sek       = r19
    .def   sicher    = r20
    .def   Delay     = r23
    .def   Count     = r24

    ;Port B
    .equ   TXD      = 1    ;TXD Senden  PB1
    .equ   RXD      = 2    ;RXD Empfang PB2
    .equ   Eingang  = 3    ;Messeingang PB3


        rjmp Anfang        ;Springe nach Anfang
        .org 0x0003
        rjmp TIM0_OVF

Anfang:
        sbi    ddrb,TXD    ;SBI=Setze Bit In DDRB 1
        ldi    A,7         ;LDI=Lade Register mit Wert 7
        out    TCCR0B,A    ;Start mit positiven Flanke
        ldi    A,2         ;LDI=Lade Register mit Wert 2
        out    TIMSK0,A    ;Timer Interrupt freigeben
        clr    timer       ;r17 löschen
        clr    timer2      ;r18 löschen
        clr    sek         ;r19 löschen
        sei
        
Schleife:
        cpi    sek,1        
        rcall  Lesen
        in     A,TCNT0
        rcall  WrCOM      
        rjmp   Schleife

TIM0_OVF:                  ;Timer Interrupt
        in    sicher, SREG ;Statusregister in r20 kopieren
        ldi   timer, 6     ;LDI=Lade Register mit Wert 6
        out   TCNT0,timer  ;TCNT0 auf 6 setzen 256-6=250 bis Overflow
        inc   timer2       ;Registerinhaltinhalt um 1 erhöhen
        cpi   timer2,75    ;Vergleich Register mit Wert 75
        brlo  TIM0_ende    ;Sprung, wenn kleiner (Vorzeichenlos)
        clr   timer2       ;r18 löschen
        nop
        inc   sek          ;Registerinhaltinhalt um 1 erhöhen
TIM0_ende:
        out   SREG,sicher  ;r20 in Statusregister kopieren
        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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Initialisierung vom Stackpointer vergessen.

MfG Spess

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie macht man das?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

MfG Spess

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke werde ich gleich mal testen.

MfG
Rufus

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
;Frequenz.asm, Frequenzmessung an PB4

    .include "tn13def.inc"

    .def   A      = r16
    .def   timer  = r17
    .def   timer2 = r18
    .def   sek    = r19
    .def   sicher = r20
    .def   freqlow   = r21
    .def   freqhigh  = r22
    .def   Delay  = r23
    .def   Count  = r24

    ;Port B
    .equ   TXD    = 1
    .equ   RXD    = 2


        rjmp Anfang
        .org 0x0003 
        rjmp TIM0_OVF    ;Timer0 Overflow 
Anfang:
        sbi    ddrb,TXD    
        sbi    ddrb,3    
        ldi    A,3        ;Start mit Vorteiler / 64
        out    TCCR0B,A
        ldi    A,2
        out    TIMSK0,A     ;Timer Interrupt freigeben
Schleife:
        clr    timer2
        clr    sek
        clr    freqlow
        clr    freqhigh
        sei                ;Interrupt freigeben   
Z1:     sbic   pinb,4        
        rjmp   Z2
        sbi    portb,3     ;Testsignal
        cpi    sek,1
        brsh   Z4
        rjmp   Z1
Z2:     sbis   pinb,4
        rjmp   Z3
        cbi    portb,3     ;Testsignal
        cpi    sek,1
        brsh   Z4
        rjmp   Z2
Z3:     inc    freqlow
        brne   Z4
        inc    freqhigh
Z4:     cpi    sek,1
        brlo   Z1
Z5:     cli                ;Interrupt sperren
        mov    A,freqhigh
        rcall  WrCOM
        mov    A,freqlow
        rcall  WrCOM
        rjmp   Schleife


TIM0_OVF:                  ;Timer Interrupt
        in    sicher, SREG 
        ldi   timer, 6 
        out   TCNT0,timer  ;250 bis Overflow
        inc   timer2
        cpi   timer2,75
        brlo  TIM0_ende
        clr   timer2
        inc   sek
TIM0_ende:
        out   SREG,sicher
        reti

RdCOM:  sbis  pinb,RXD  ;Empfangen
        rjmp  RdCOM
        ldi   Delay,58  
D1:     dec   Delay
        brne  D1
        ldi   A,0
        ldi   Count,8
L1:     lsr   A
        sbic  pinb,RXD
        ori   A,128
        ldi   Delay, 38  
D2:     dec   Delay
        brne  D2
        dec   Count
        brne  L1
        ldi   Delay, 38
D3:     dec   Delay
        brne  D3
        com   A
        ret

WrCOM:  sbi   portb,TXD  ;Senden
        ldi   Delay,38 
D4:     dec   Delay
        brne  D4
        ldi   Count,8
L2:     sbrc  A,0
        rjmp  OFF
        rjmp  ON
ON:     sbi   portb,TXD
        rjmp  BitD
OFF:    cbi   portb,TXD
        rjmp  BitD
BitD:   ldi   Delay,38  
D5:     dec   Delay
        brne  D5
        lsr   A
        dec   Count
        brne  L2
        cbi   PORTB,TXD
        ldi   Delay,38  
D6:     dec   Delay
        brne  D6
        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?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
;Pulsbreitenmessung (vereinfacht)

    .include "tn13def.inc"

    .def  A        = r16
    .def  timer    = r17

Beginn:
    ldi    A,0            ;TCNT0 leeren
    out    TCNT0,A
loopa:
    sbis   pinb,4         ;PB4 abfragen
    rjmp   loopa          ;wiederholen
    rjmp   Tgo            ;weiter, wenn Signal da ist
Tgo:
    ldi    A,1            ;Timer aktiveren ohne Vorteiler
    out    TCCR0B,A
loopb:
    sbis   pinb,4         ;PB4 abfragen
    rjmp   Tstop          ;Sprung, wenn kein Signal
    rjmp   loopb          ;Abfrage wiederholen
Tstop:
    ldi    A,0            ;Timer stoppen
    out    TCCR0B,A
    clr    timer           
    in     timer,TCNT0    ;Timerwert auslesen zur
                          ;Weiterverarbeitung
    rjmp  Beginn
Für jeder Art Tips bin ich sehr dankbar.

MfG Rufus

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.