Forum: Mikrocontroller und Digitale Elektronik ungewolltes schwanken von Pulsweiten


von Jan L. (jan_l)


Lesenswert?

Hallo,

Ich weiß nicht genau wie ich anfangen soll.


Es geht darum, fortlaufend einen Puls zu generieren, der später dann als 
Trigger für ein anderes Gerät dienen soll. Um den Puls zu generieren 
verwende ich im Moment ein Arudino Leonardo Board.

Nun zu meinem Problem. Es ist leider nötig, das dieser Puls so wenig wie 
möglich schwankt. So wenig wie möglich heisst, am besten garnicht.

Nun anfangs habe ich versuch den Puls einfach mit dem Delay von Arduino 
zu realisieren.

Da kamen wenn ich es mir auf dem oszi angeschaut habe allerdings 
schwankungen von bis zu 200µs raus. mein nächster schritt war es, den 
Flankenwechsel mit einem Timer auszulösen (zb. alle 5ms) diesen hatte 
ich dank eine library als interrupt fungieren lassen. da wurde es mit 
der zeit auch schon bisschen besser (schwankungen zwischen 10 - 30 µs). 
Leider ist das auch immer noch viel zu viel.

Also dachte ich mir, lass ich Arduino halt ganz beiseite. momentan sieht 
meine Umsetzung also folgendermaßen aus:
1
int pin = 10;
2
3
void setup(){
4
  pinMode(pin, OUTPUT);
5
  
6
  noInterrupts();
7
  TCCR1A = 0;        // TCCRx - Timer/Counter Control Register
8
  TCCR1B = 0;
9
  TCNT1  = 0;        
10
  
11
 
12
  TCNT1 = 64911;
13
  TCCR1B |= (1 << CS10);    // no prescaler 
14
  TIMSK1 |= (1 << TOIE1);  // compare interrupts OCIE1A
15
  interrupts();            // enable all interrupts
16
  
17
}
18
19
ISR(TIMER1_OVF_vect)          // timer compare interrupt service routine  TIMER1_COMPA_vect
20
{
21
  TCNT1 = 64911;
22
  digitalWrite(pin, digitalRead(pin)^1);   // toggle pin
23
}
24
25
void loop()
26
{
27
}

In der Version bekomme ich eine Schwankung von ca.7 - 8 µs allerdings 
dachte ich dass ich durch das umgehen von Arduino doch auf eine 
wesentlich konstantere Zeit kommen würde.

Hat irgendjemand eine idee was ich 1. Falsch mache bzw. 2. besser machen 
könnte?


ps.: hab es auch schon versuch den Timer auf "vergleichen zu stellen 
(CTC)" das hat allerdings wieder schlechtere Zeiten gebracht.

pss.: Ich hatte noch eine Idee allerdings fehlt es mir da an der 
Umsetzung. Da es egal ist, wie lang die Pulse sind und es nur wichtig 
ist, das die Steigenden Flanken 100% konstante Abstände haben: Kann ich 
dem Arduino nicht irgendwie sagen "Geh jetzt hoch - geh jetzt runter - 
mach eine gewisse zeit was du möchtest - geh aber gefälligst exakt da 
wieder hoch " usw.


Ich hoffe man hat verstanden wo mein Problem bzw was meine Frage ist. Da 
ich in dem Thema doch recht neu bin fällt es mir durchaus schwer immer 
die richtigen und passenden Worte für alles zu finden :P

: Verschoben durch User
von troll (Gast)


Lesenswert?

Lass den AVR den Puls mittels Timer in Hardware erzeugen. PWM, CTC 
und toogle pin on compare oder so, guck halt ins Datenblatt.

von icke (Gast)


Lesenswert?

Soweit ich weiß ist das Setzen von Pins mit Arduino ziemlich Ressourcen 
fressend.
Also einfach das DDR (Data Direction Register) von deinem gewünshten 
Port setzen und mit PORTX den Pin zappeln lassen.

von Michael (Gast)


Lesenswert?

troll schrieb:
> Lass den AVR den Puls mittels Timer in Hardware erzeugen. PWM, CTC
> und toogle pin on compare oder so, guck halt ins Datenblatt.

Hast du den Quellcode überhaupt angeschaut? Er verwendet schon den Timer 
zum Toggeln ...

icke schrieb:
> Soweit ich weiß ist das Setzen von Pins mit Arduino ziemlich Ressourcen
> fressend.
> Also einfach das DDR (Data Direction Register) von deinem gewünshten
> Port setzen und mit PORTX den Pin zappeln lassen.

Hä was bitte? Pin setzen ist ressourcenfressend? Bist du hacke? 
Schreibst erst, es wäre ressourcenfressend (was völlig daneben ist) und 
sagst, dann er soll es machen? Was würdest du denn tun? Pins nicht 
setzen ???

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> troll schrieb:
>> Lass den AVR den Puls mittels Timer in Hardware erzeugen. PWM, CTC
>> und toogle pin on compare oder so, guck halt ins Datenblatt.
>
> Hast du den Quellcode überhaupt angeschaut? Er verwendet schon den Timer
> zum Toggeln ...

Schon.
Aber er toggelt den Pin mit einer ISR.

Das kann der Timer auch ganz alleine machen.
Und dann ist es auf den Quarz-Taktzyklus genau.

Einziger Nachteil: Man ist an den betreffenden Hardware-Pin gebunden. 
Den gibt Atmel vor.

Daher - Datenblatt

> ... Pins nicht setzen ???

Doch natürlich. Aber nicht über diese eierlegende Wollmilchsau, die die 
Arduino digitalWrite Funktion darstellt. Für eine derartige 
Trivialaufgabe braucht in Wirklichkeit kein Mensch das Ardunio-API.

Allerdings gibt es, wie bereits gesagt, eine noch bessere Lösung: Lass 
die Hardware arbeiten.

von spontan (Gast)


Lesenswert?

>Hast du den Quellcode überhaupt angeschaut? Er verwendet schon den Timer
>zum Toggeln ...

Ho, immer langsam mit den jungen Pferden. Du verwendest eine 
Interruptroutine zum Toogle des Pin. Exaktes Timing kannst Du da nicht 
erwarten. Nur besseres als ohne Timerinterrupt.

Du mußt einen Hardwarepin eines Timers als Ausgang verwenden. Setzten, 
laufen lassen, nicht mehr mit der Software anfassen. Das gibt ein festes 
Timing.

von spontan (Gast)


Lesenswert?

@Michael: Nix gecheckt, oder?

von Jan L. (jan_l)


Lesenswert?

So,

also der PWM war eine super Idee. Ist zwar schon deprimierend, dass z.B.
1
void setup(){
2
  analogWrite(6, 8);
3
}
4
void loop(){}

genauso genau ist wie mein oben Implementiertes...
Da mir aber langsam die Programmierkenntnisse ausgehen (um analogWrite) 
selber zu programmieren wird es wohl eher nicht mehr genauer. Allerdings 
hat mir jetzt ein Kollege angeboten mir zu helfen den Puls komplett mit 
Hardware umzusetzten. Da ich davon aber garkeine Ahnung hab bin ich mal 
gespannt was dabei rauskommt...

von Axel S. (a-za-z0-9)


Lesenswert?

Jan L. schrieb:

> ... PWM war eine super Idee. Ist zwar schon deprimierend, dass z.B.

1
void setup(){
2
  analogWrite(6, 8);
3
}
4
void loop(){}

> genauso genau ist wie mein oben Implementiertes...

Das dürfte dann aber daran liegen, daß die Funktion analogWrite() auf 
untaugliche Art implementiert ist. Also eben z.B. die Pins in Software 
setzt. Scheint aus der Arduino-Ecke zu kommen, die ich nun gar nicht 
kenne (und auch nicht kennen will).

> Da mir aber langsam die Programmierkenntnisse ausgehen (um analogWrite)
> selber zu programmieren wird es wohl eher nicht mehr genauer.

Du brauchst ja gar keine PWM. Schnapp dir das Datenblatt des µC auf 
deinem Board und lies das Kapitel über Timer durch. Insbesondere den 
Teil zu Output-Compare. Das ist keine Raketentechnik.


XL

von Karl H. (kbuchegg)


Lesenswert?

Axel Schwenke schrieb:

> Das dürfte dann aber daran liegen, daß die Funktion analogWrite() auf
> untaugliche Art implementiert ist. Also eben z.B. die Pins in Software
> setzt. Scheint aus der Arduino-Ecke zu kommen, die ich nun gar nicht
> kenne (und auch nicht kennen will).

Am Arduino haben sie das 'Problem', dass sie analoge Ausgabe auf mehr 
Pins machen wollen, als der µC überhaupt Timer hat. Damit ist klar, dass 
es sich um eine Software-PWM handeln muss. Geht nicht anders.

> Du brauchst ja gar keine PWM. Schnapp dir das Datenblatt des µC auf
> deinem Board und lies das Kapitel über Timer durch. Insbesondere den
> Teil zu Output-Compare. Das ist keine Raketentechnik.

Exakt.
Also das mit der Raketentechnik.

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.