Forum: Mikrocontroller und Digitale Elektronik Pulsweitenmessung


von Hasibeder Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo an das Forum!

Ich habe mir alle Beiträge zur Pulsweitenmessung durchgelesen und 
durchgedacht und das nicht nur auf dieser Seite.
Leider Funktioniert mein Programm noch immer nicht.
Im Anhang als Text Datei.

Ich verwende ein AVR Board zur Programmierung und zum Testen.
Ich habe das Programm mit den Interrupts aufgebaut.
Die LEDs verwende ich zur Kontrolle in welchem Programmteil der 
uC(ATMega32) gerade ist.
Ich habe einen Schalter am ICP1 Pin mit dem ich Flanken simuliere, 
leider kommt der Interrupt nicht und ich komme nicht dahinter warum.
Programmiert wurde mit AVR Studio 5 und einem AVRISPmk2.
Keine Warnungen und keine Fehler.

Die Spannung am ICP1 Pin liegt zwischen 0V und 5V beim Schalten 
(gemessen).

Könnte mir jemand Verbesserungsvorschläge nennen oder mich auf den 
Fehler bringen bitte?

Danke schon im vorhinein.

Mfg

von Georg G. (df2au)


Lesenswert?

Was hältst du davon, die Timer Interrupts in TIMSK frei zu geben?

von spess53 (Gast)


Lesenswert?

Hi

>Im Anhang als Text Datei.

Das nächste mal als .c-Datei.

MfG Spess

von Hasibeder Thomas (Gast)


Lesenswert?

Ok, hab jetzt als Hex zahl initialisiert. Hatte ich schon einmal ging 
aber damals nicht. Jetzt schon!

Jetzt ist natürlich der Timer im Überlauf.
Aber ich habe gedacht das der Interrupt wieder verlassen wird, er bleibt 
aber ständig im Overflow Interrupt.
Ist es richtig das wärend der Interrupts keine weiteren Interrupts 
kommen können?

von holger (Gast)


Lesenswert?

>er bleibt aber ständig im Overflow Interrupt.

Ob das wohl an deinen
  wait_ms (1000);

in den Interrupts liegt? So ein Müll gehört
nicht in Interrupts, egal in welche.

Deine main() hat keine Endlosschleife.

von innerand i. (innerand)


Lesenswert?

Hallo Thomas,

Interrupt-Routinen sollten grundsätzlich so kurz wie möglich gehalten 
werden.

sowas wie
1
 wait_ms(1000);
will man da also auf keinen Fall drinnen haben.

von Hasibeder Thomas (Gast)


Lesenswert?

OK habe ich rausgeworfen und die Messung müsste jetzt Funktionieren.
Das HP hat auch eine Endlosschleife bekommen.

Danke schon mal für eure schnelle Hilfe. Bin zwar Neuling aber sind doch 
dumme Fehler.

Ich will jetzt ein PWM Signal aus der gemessenen Pulsweite erzeugen und 
am OC0 ausgeben.

Es geht um eine Verbindung von der Fernsteuerung zu einem Motortreiber.

Die Geradengleichung soll zum Umskalieren dienen.
Pulsweiten von der Fernbedienung sind 1,4ms bei Stillstand und 2,1ms bei 
Vollgas.
Laut meiner Rechnung sollte er von 11200 bis 16800 Zählen, je nach 
Stellung.
Skalierung auf 0 bis 255 für Timer 0, der dann ein PWM erzeugen sollte.


Stimmt mein Grundgedanke? Kann das Funktionieren?

Danke

von innerand i. (innerand)


Lesenswert?

Noch ein paar Anmerkungen:

Ich denke das Stoppen und Zurücksetzen des Timers kannst du dir sparen. 
Der kann einfach immer durchlaufen.
Ein Überlauf sollte hier egal sein, da es bei der Differenzbildung 
wieder zu einem "Überlauf" kommt und somit auch bei einem 
Counter-Überlauf das korrekte Ergebnis rauskommt (kaputt ist es erst, 
wenn er innerhalb eines Pulses zwei mal überläuft). Der ganze 
Overflow-Interrupt Geschichte kann also weg.

Variablen die du in der Interrupt-Routine änderst sollten als volatile 
deklariert werden, ansonsten kann es sein, dass der Compiler da was rum 
optimiert und Änderungen der Variable nicht berücksichtigt werden.

Ich würd's in etwas so machen:
(nicht getestet)
1
...
2
volatile unsigned int newPulseWith = 0;
3
volatile unsigned int pulseInUs = 0;  
4
unsigned int pulseStart = 0;
5
unsigned int pulseEnd = 0; 
6
...
7
8
ISR(TIMER1_CAPT_vect)                 
9
{ 
10
   if(TCCR1B & (1 << ICES1)) //rising Edge
11
   {
12
      pulseStart=ICR1;
13
      TCCR1B &= ~(1 << ICES1);              
14
   }
15
   else                     //falling Edge
16
   {
17
    pulseEnd = ICR1;                     
18
    TCCR1B |= (1 << ICES1);
19
    pulseInUs = pulseEnd-pulseStart;
20
    newPulseWith = 1; 
21
   }
22
}
23
24
int main(void)
25
{
26
    ...
27
    while(1)
28
    {
29
        ...
30
        if(newPulseWith)
31
        {
32
            ...
33
            //skalierung von pulseInUs
34
            ...
35
            PWM_set(...)
36
            newPulseWith = 0; 
37
        }
38
        ...
39
    }
40
}

: Bearbeitet durch User
von Hasibeder Thomas (Gast)


Lesenswert?

Danke! Dein Programm läuft auch ja!

Pulsweitenmessung sollte Funktionieren.

Jetzt habe ich ein nächstes Problem.
Ich will über einen BTN7970 Motortreiber auf den Motor.
Am IN Pin hänge ich den OC0 Pin an.(PB.3)
Das Programm gibt laut LED Anzeige ein PWM aus.
Es sind aber dauernd 5V am PB.3 Pin. Der Mittelwert der PWM sollte sich 
doch verändern.

Es rührt sich aber auch nichts am Motor.

Habe es auch mit prescaler versucht da der BTN7970 mit bis zu 25kHz 
arbeitet.

Mfg

von spess53 (Gast)


Lesenswert?

Hi

>Ich will über einen BTN7970 Motortreiber auf den Motor.

Zeig mal die Schaltung. Ein BTN7970 macht nicht wirklich Sinn.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Hasibeder Thomas schrieb:
> Danke! Dein Programm läuft auch ja!
>
> Pulsweitenmessung sollte Funktionieren.

Was heißt 'sollte'?

Funktioniert sie oder funktioniert sie nicht!
Wenn du es nicht weißt, dann musst du dir eben einen Test überlegen, mit 
dem du das feststellen kannst. Und zwar einen möglichst einfachen Test, 
damit die Chance, dass du im Test selbst wieder Fehler hast möglichst 
gering ist.

Gleich mal mit dem ermittelten Wert wieder auf eine PWM zu gehen, ist 
für einen Profi vielleicht ein gangbarer Test-Weg, für einen Neuling 
aber eher nicht. Für einen Neuling wäre der allerbeste 'Test', sich den 
ermittelten Wert auf einem LCD oder über UART auszugeben, damit man die 
Zahlenwerte sieht. Leider denken Neulinge immer, ausgerechnet sie sind 
die Wunderwuzzi, die so etwas nicht brauchen und daher planen sie auch 
bei ihren ersten Projekten keine Ausgabemöglichkeit ein. Was regelmässig 
immer wieder zu Problemen führt. Aber gut, ist halt so.
Dann muss eben Plan B greifen und man muss den Test auf die aufwändige 
Art und Weise machen: Eine LED an einem Ausgangspin. Ist der ermittelte 
Messwert größer als eine Grenze, wird sie eingeschaltet, ist er kleiner 
wird die LED ausgeschaltet. Durch Variation der Grenze kann man dann den 
ermittelten Wert auch einigermassen gut feststellen. Was bei dir 
natürlich insofern ganz gut funktioniert, weil du dann die LED 'vom 
Fernsteuersender aus' durch Knüppelbewegung ein bzw. ausschalten können 
müsstest und durch verändern des Grenzwertes im Programm den Schaltpunkt 
am Knüppel 'verschieben' kannst.

Ohne so einen Test, bei dem man sich davon überzeugt, dass die 
ermittelten Werte auch tatsächlich so sind wie sie sein sollten, ist es 
jedenfalls unklug, da gleich mal die nächste Stufe - Ansteuerung 
Motortreiber mittels PWM - drauf zu setzen. Du hast dann 2 Teilsysteme 
im Programm, von denen du nicht weißt ob sie funktionieren oder nicht. 
Alles was du siehst ist: nichts geht. Aber du hast keine Ahnung warum. 
Sind die ermittelten Werte falsch oder ist die Motoransteuerung 
fehlerhaft?


Und nein: nur weil der Compiler keinen Senf mehr zu deinem Programm dazu 
gibt, heißt das noch lange nicht, dass es funktioniert. Der Compiler 
kümmert sich darum, dass deine Grammatik korrekt ist. Um die Logik in 
deinem Programm musst du dich schon selbst kümmern. Der Herr Duden hat 
auch an dem Satz "Das Flugzeug strickt die Weltmeere." erst mal nichts 
auszusetzen. Grammatikalisch ist alles korrekt. Aber die Logik, die 
Bedeutung, ist völlig daneben.

: Bearbeitet durch User
von innerand i. (innerand)


Lesenswert?

Hasibeder Thomas schrieb:

> Am IN Pin hänge ich den OC0 Pin an.(PB.3)
> Das Programm gibt laut LED Anzeige ein PWM aus.
> Es sind aber dauernd 5V am PB.3 Pin. Der Mittelwert der PWM sollte sich
> doch verändern.

Hast du deine wait Funktion noch irgendwo in Verwendung?
Die nutzt nämlich Timer0, also den selben über den auch die PWM laufen 
soll...

von Hasibeder Thomas (Gast)


Lesenswert?

Danke für eure Hilfe!

Bin jetzt dabei über UART und dem Terminal alles zu kontrollieren.
Wenn alles Funktioniert melde ich mich wider.

Mfg

von Hasibeder Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Ausgabe Funktioniert aber leider die Messung noch nicht.
Habe jetzt den prescaler auf /64 gestellt und den noise canceler. Nutzte 
aber auch nicht. Zählt irgendwas und sollte mit dem prescaler auf 175 
kommen bei stillstand.

Bin wider etwas ratlos obwohl die Sache sicher wider recht einfach ist.

Auf jeden Fall danke für eure Hilfe.
Ich habe schon einiges gelernt in den letzten Tagen und will auch in 
Zukunft damit Modellautos programmiern und verwirklichen.

Mfg

von Hasibeder Thomas (Gast)


Lesenswert?

Hallo,

Ich glaube das Signal von der Fernbedienung wird vom uP nicht erkannt.

mfg

von Hasibeder Thomas (Gast)


Lesenswert?

Was würdest du mir raten. Brauche einen Motortreiber.

Mfg

von Karl H. (kbuchegg)


Lesenswert?

Hasibeder Thomas schrieb:

> Zählt irgendwas

was bedeutet 'irgendwas'.

von Hasibeder Thomas (Gast)


Lesenswert?

Hallo,

Also irgendetwas jetzt nicht mehr da ich das Problem entdeckt habe.
Ich habe kein TTL Signal sondern nur einen Sprung von 0,2V was zu wenig 
ist.
Versuche Morgen alles zu Kontrollieren.
Mein Plan sieht jetzt eine Messung über den ADC.
Theoretisch ja such möglich, Programmtechnisch sehe ich das Morgen.

Mfg

von Karl H. (kbuchegg)


Lesenswert?

Hasibeder Thomas schrieb:

> Also irgendetwas jetzt nicht mehr da ich das Problem entdeckt habe.
> Ich habe kein TTL Signal sondern nur einen Sprung von 0,2V was zu wenig
> ist.

Hast du einen µC mit der Fernsteuerungsmasse (GND) verbunden?
0.2V ist viel zu wenig. Aus einem Fernsteuerungsempfänger kommen Pulse 
mit dem Hub der aktuellen Versorgungsspannung raus. ALso das, was dein 
Akku zur Zeit gerade liefert. Also irgendwas rund um 5V. Mehr als genug, 
dass dein Mega damit was anfangen kann.

> Mein Plan sieht jetzt eine Messung über den ADC.

Falscher Weg.
Du hast irgendein elektrisches Problem.

von Hasibeder Thomas (Gast)


Lesenswert?

Hallo,

Wie muss ich den Anschließen?
Habe einen SANWA RX 451 und einen ATMega 32
DER RX451 braucht 5V Versorgung.

Mfg

von Karl H. (kbuchegg)


Lesenswert?

Und der Mega steckt 'wie ein Servo' an einem Servo-Ausgang?

Dann schliesst du ihn auch genau so an, wie ein Servo angeschlossen 
werden würde.
Einzige Ausnahme: wenn der Mega seine eigene Stromversorgung hat, dann 
wird die positive Versorgungsspannung nicht am Empfänger angeschlossen. 
Aber Puls und Masse müssen auf jeden Fall an den Empfänger. (Also 'S' 
und '-' am Sanwa Empfänger)

: Bearbeitet durch User
von Hasibeder Thomas (Gast)


Lesenswert?

Ok Danke.
Weis nicht warum. habe ein bisschen herumgesteckt und jetzt ist alles 
wie vorher aber es geht.

zumindest auf dem AVR Board.
Auf dem Steckbrett noch nicht.
Fehlt wohl etwas.

Mfg

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.