www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Ich suche eine schnelle Lösung für eigenes delay_us


Autor: Barny F. (barny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag

Ich möchte mit einem ATtiny24 mir 8MHz Takt ein asymetrisches 
Rechtek-Signal generieren (low < high) dass eine Periodendauer von bis 
zu 2,5ms hat.
Hat jemand eine Idee wie ich dass Signal genau timen kann?
Dass Blöde ist, dass ich eine Auflösung von ca. 0,05ms brauche.
Da die Hauptschleife nichts anderes zu tun hat als das Signal zu 
generieren, währe es am Einfachsten wenn ich für das Generieren des 
Signals delay_us verwenden würde.
Aber dass will ja bekanntlich unter CodeVisionAVR nur statische Werte 
und unter WinAVR nur Intervalle die nicht für diese Zeitdauer geeignet 
sind.

Der 16 Bit Timer 1 läuft mit Prozessortakt / 4, der 8 Bit Timer0 mit 
Prozessortakt / 32.
Die zu generierenden Zeitdauern liegen als us-Wert in 16Bit Variablen 
vor.

Hat jemand eine Idee wie ich dass lösen kann?
Leider bin ich in ASM eine absolute Niete und brauche eure Hilfe.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Barny F. (barny)

>Ich möchte mit einem ATtiny24 mir 8MHz Takt ein asymetrisches
>Rechtek-Signal generieren (low < high) dass eine Periodendauer von bis
>zu 2,5ms hat.
>Hat jemand eine Idee wie ich dass Signal genau timen kann?

Mit einem Timer und der Output Compare Funktion.

>Dass Blöde ist, dass ich eine Auflösung von ca. 0,05ms brauche.

50us.

>Da die Hauptschleife nichts anderes zu tun hat als das Signal zu
>generieren, währe es am Einfachsten wenn ich für das Generieren des
>Signals delay_us verwenden würde.

Nö.

>Aber dass will ja bekanntlich unter CodeVisionAVR nur statische Werte
>und unter WinAVR nur Intervalle die nicht für diese Zeitdauer geeignet
>sind.

Nö.

MfG
Falk

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ein asymetrisches Rechtek-Signal generieren (low < high) dass eine
> Periodendauer von bis zu 2,5ms hat.
Sowas nennt der Fachmann PWM

> Der 16 Bit Timer 1 läuft mit Prozessortakt / 4, der 8 Bit Timer0 mit
> Prozessortakt / 32.
Evtl. kannst du den Timer 1 irgendwie freimachen und für deine PWM 
verwenden?

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servos?
Wenn deine kleinste Auflösung 50µs ist, kannst du ein so großes delay_us 
verwenden und zählen, wie oft das abgearbeitet wird.

Richtige Lösung sind timer/pwm.

Autor: Barny F. (barny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PWM kann ich leider nicht verwenden, da es sich um ein Signal handelt 
und ich dass Puls-Pausenverhältnis nicht hinbekomme.

Wie avion23 richtig vermutet handelt es sich um ein PPM Signal.
Aber leider handelt es sich nicht um ein gemütliches Servosignal sondern 
um ein 8-Kanal PPM Summensignal welches aus dem Signal des Empfängers 
generiert wird.
(je 3us bis 6us  Pause zwischen den 0,8 bis 2,2ms langen Impulsen)

Wenn ich meine Anlage als Ausgang nehme habe ich da 8 Kanäle mit je 10 
Bit Auflösung.
Dass die Kanäle eine gemeinsame steigende Flanke haben, macht es einem 
auch nicht leichter.

Desswegen möchte ich nicht all zuviel an Daten bei der Umwandlung 
verlieren.
Die Auflösung des generierten Signals sollte möglichst nahe bei den 
10Bit liegen.

Da ich den Timer1 schon zum Ermitteln der Zeiten der einzelnen Kanäle 
verwende, kann ich leider nicht mit output compare arbeiten.

Ich weis dass es solche Wandler schon zu kaufen gibt.
Aber ich will mir erstens soetwas selbst bauen und außerdem brauche ich 
ein paar spezielle Funktionen.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann generiere dir doch interrupts alle 50µs, und frage im interupt ab, 
welches tastverhältnis du brauchst, also wann du auf high und wann du 
auf low schaltest. So hast du eine Einstellmöglichkeit von HI time und 
LOW time.

Einziger Nachteil: hohe CPU-Auslastung, wenn du wirklich sehr 
oft(festgemacht an der Auflösung) einen Interrupt auslöst. Andersherum 
denke ich, dass du mit der Auslastung gut leben kannst, da du ja mit 
8MHz taktest.

du kannst im interrupt zwei counter inkrementieren:
in c: a++;b++;
dann abfragen, ob a == HI-zeit/auflösung
und ob b == LOW-zeit/auflösung

pin ensprechend toggeln

verstanden?

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bsp:

1ms auf hi 2ms auf low sind bei einer auflösung(timerinterrupts) von 
50µs
dann 20 ints auf low und 40 ints auf hi


im interrupt:
also eine zählervariable inkrementieren
ist die zählervariable <= hizeit/50µs dann Pin auf HI
ist die zählervariable > hizeit/50µ dann pin auf LOW

ist sie bei (hizeit/50µs + lowzeit/50µs) // also bei 20+40
dann musst du sie wieder auf 0 setzen.

interrupt zu ende

Autor: Barny F. (barny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daran hatte ich auch schon gedacht.
Aber dass wird nichts.

Die 50us ist dass maximal vertretbare.
Lieber währe mir ein Faktor 10 bis 100 schneller.
Die 50us Auflösung ist ja schon fast im Bereich "binäre Steuerung"

Und bei dieser Methode komme ich den Interupts der eingelesenen Signale 
in die Quere.

Timo, das PPM Signal sieht übrigens folgendermaßen aus:
Der Empfänger liefert 8x folgendes Signal:
Ein 0,8ms bis 2,2 ms high Pegel, gefolgt von einem längeren Lowpegel der 
je nach Fernbedienungshersteller bis zu 20ms lang sein kann.
Leider kommen bei den neuen Digitalsendeanlagen die steigende Flanke bei 
mehreren bzw. allen Kanälen gleichzeitig.

Und folgendes Signal soll aus den 8 parallelen Signalen generiert 
werden:
die 8 einzelnen empfangenen Signale sollen hintereinander gereit und dur 
3us Pausen getrennt ausgegeben werden.
Nach diesem Impulspaket kommt eine Pause die 7ms lang ist und dann geht 
dass Ganze wieder von vorne los.


Würde folgendes funktionieren?

Ich setze am Anfang des Signal-Frames TCNT1 auf 0x0000.
Dann überprüfe ich in einer Schleife ob der Timer einen bestimmten Wert 
erreicht/überschritten hat und schalte den Ausgang um.
Nach der Wartezeit von 3us zur Signaltrennung legt man den Ausgang auf 
high und wartet wieder bis der Timer den richtigen Wert erreicht hat um 
den Ausgang auf low zu legen.

Dass Ganze wird 8 mal gemacht.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Barny F. schrieb:

> PWM kann ich leider nicht verwenden, da es sich um ein Signal handelt
> und ich dass Puls-Pausenverhältnis nicht hinbekomme.

Timer mit Interrupt und Pin-Change, im Interrupt jeweils die naechste 
Zeit setzen. Fertig und sehr genau.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Barny F. schrieb:
> Und folgendes Signal soll aus den 8 parallelen Signalen generiert
> werden:
> die 8 einzelnen empfangenen Signale sollen hintereinander gereit und dur
> 3us Pausen getrennt ausgegeben werden.
> Nach diesem Impulspaket kommt eine Pause die 7ms lang ist und dann geht
> dass Ganze wieder von vorne los.

Das Erzeugen ist doch popeleinfach. Du nimmst den Compare-Interrupt und 
der Pin wird mit dem Compare gesetzt oder gelöscht. Und im 
Compareinterrupt lädst Du ganz bequem den nächsten Zeitpunkt in das 
Compareregister.
Die Pulsdauer ist damit auf exakt einen CPU-Zyklus genau (0,125µs).


Schwieriger ist da schon das parallele Empfangen von 8 Signalen. Dazu 
müßte man den Pin-Change-Interrupt nehmen und den Timestamp in Software 
auslesen.
Damit hat man aber mehrere CPU-Zyklen Fehler.

Vorteilhaft ist, daß beides mit Timer1 gemacht werden kann, da der 
durchlaufen muß.


Peter

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau so wie Peter Dannegger &  Peter Stegemann habe ich es auch gelöst. 
Das funktioniert einwandfrei. Wenn du den Timer 1:1 laufen lässt ist die 
Auflösung nur durch deinen CPU Takt und 16bit begrenzt.
Leider hast du auch eine Verzögerung bis zu 20ms. Das kann auch 
erwünscht sein, weil dann nicht alle Servos gleichzeitig schalten.

Autor: Barny F. (barny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter Dannegger und Peter Stegemann
Danke ihr beiden.
Da sieht man wieder was für ein schmarrn rauskommt wenn man sich in 
irgend etwas verannt hat. Da sieht man das Byte vor lauter Bits nicht 
mehr.

@Peter Dannegger
Für das Einlesen verwende ich schon den PCINT.
Da diese Fehler bei jedem Kanal aber einigermaßen konstant ist, kann man 
ihn einigermaßen genau herausrechnen.

@avion23
Ich glaube du hast mich nicht ganz verstanden.
Ich will nicht ein PPM Summensignal in ein paralleles umrechen wie es 
die Empfänger machen, sondern die andere Richtung.
Wenn ich da ein Servo anschließe, wird es mir etwas husten.
Kannst du mir bitte sagen wo da eine Verzögerung von 20ms herkommt?
Dass Blöde ist eher dass mir die Eingangssignale davonlaufen da das 
seielle Datenpaket dass generiert wird aufgrund der Anpassung der 
Sicherheitsabstände zwischen den Daten und den Datenpaketen etwas länger 
ist.

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.