Forum: Compiler & IDEs Delay-Funktion mit variablem Parameter aufrufen


von muckelsoft (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich möchte eine LED an einem Pin des ATmega8 blinken lassen.
Das Warten zwischen dem High- und dem Lowsetzen des Pins
möchte ich mit der _delay_ms() funktion realisieren.
Statt eines festen Wertes für die delay-funktion,
möchte ich jedoch einen Parameter übergeben, welchen ich
während der Programmlaufzeit verändern kann.
Also in dem ich 2 weitere Pins als Eingänge definiere und wenn
ich diese jeweils auf high lege, soll der an delay übergebene
Parameter erhöht o. verringert werden.
Die Programmierung erfolgt mit C im AVR-Studio, als Compiler
verwende ich den GCC.
Im Anhang habe ich einen Codeausschnitt eingefügt, wie ich es
realisieren würde.
Mein Problem ist, dass ich jedeoch die Wartezeit während 
Programmausführung auf dem µC nicht beeinflussen kann.
Übergebe ich delay einen festen Wert u. lasse das herauf- / herabsetzen 
der Wartezeit weg, blinkt die LED wie gewünscht.
Binde ich aber die While-schleifen zum wartezeit erhöhen o. verringern 
ein, lässt sich die delay-funktion nicht wie gewünscht beeinflussen.
Mir ist leider nicht ganz klar wo hier das Problem liegt und wie ich 
diesen Fehler umgehen kann.
Ich würde mich freuen wenn mir jemand einen Tipp geben könnte wie sich 
das geschilderte Problem mit Hilfe der Delay Funktion lösen lässt.

Vielen Dank.

von Falk B. (falk)


Lesenswert?

@ muckelsoft (Gast)

>Statt eines festen Wertes für die delay-funktion,
>möchte ich jedoch einen Parameter übergeben, welchen ich
>während der Programmlaufzeit verändern kann.

Mach es so.
1
void long_delay(uint16_t ms) {
2
    for (; ms>0; ms--) _delay_ms(1);
3
}

>Mein Problem ist, dass ich jedeoch die Wartezeit während
>Programmausführung auf dem µC nicht beeinflussen kann.

Doch kann man schon. Aber ein Blick in die Doku der libc verrät, dass 
man die Funktion nur mit einem konstantem Paramter aufrufen sollte, weil 
sonst Fliesskommaberechnungen nötig sind.
Ausserdem sit deine Tastenabfrage nicht viel wert. Nicht enprellt und 
auserdem viel zu schnell.

MFG
Falk

von muckelsoft (Gast)


Lesenswert?

@ Falk:

Danke für die schnelle Antwort.
Habe deinen Vorschlag mit der For-Schleife jetzt eingebunden.
Das löst allerdings noch nicht mein Problem,
wie ich während der Laufzeit die Wartezeit fürs An/Aus der LED
beeinflussen kann. Das ist eigentlich das Hauptproblem an dem
ich nicht so richtig weiterkomme.
Ich würde den Wert für die entspr. Variable eben gerne
während der Laufzeit (m.H. der Abfrage der 2 Pins, s.Quellcode) erhöhen
oder verringern.
Selbst wenn ich die Variable zuvor mit einem Konstanten
Wert initialisiere ("int frq=30"),scheint es einfach nicht zu 
funktionieren.
Wär super wenn mir jemand sagen könnte, wie das klappen könnte...

von Karl H. (kbuchegg)


Lesenswert?

Punkt 1:
Wenn du ein Problem mit einem Programmstück hast, dann
poste das Programmstück und nicht eine Beschriebung davon

Punkt 2:

So in etwa
1
void Warte( int ms )
2
{
3
  int i;
4
5
  for( i = 0; i < ms; ++i )
6
    _delay_ms( 1 );
7
}
8
9
int main()
10
{
11
  int Wartezeit;
12
13
  while( 1 ) {
14
15
    for( Wartezeit = 10; Wartezeit < 1000; Wartezeit += 10 ) {
16
      Led_ON;
17
      Warte( Wartezeit );
18
      Led_Off;
19
      Warte( Wartezeit );
20
    }
21
  }
22
}

Nach jedem Blinken wird die Wartezeit um ein kleines bischen
länger, bis sie ihren Maximalwert von 1 Sekunde erreicht
hat. Danach geht das Spielchen wieder von vorne los.

von Eiko (Gast)


Lesenswert?

Du hast die beiden _delay_ms-Aufrufe aus deinem Code, durch ein 
long_delay(frq); ersetzt, ja?

Dann würde ich in den beiden while-Schlifen in denen frq geändert wird, 
noch ein _delay_ms(2); ('2' nur als Beispiel) einfügen, und aus der 10 
eine 1 machen. Denn sonst wird die Variable viel zu schnell rauf bzw. 
runter gezählt.


Was dein Code bissher macht, is folgendes: Wenn du PD0 auf Low setzt, 
hört die LED auf zu blinken, und du kannst mit PD1 und PD3 die 
Blinkgeschwindigkeit einstellen. Wenn du PD0 wieder auf High setzt, 
blinkt die LED mit der neuen geschwindigkeit.
Is das das was du beabsichtigst?

von muckelsoft (Gast)


Angehängte Dateien:

Lesenswert?

@ Eiko:


"Was dein Code bissher macht, is folgendes: Wenn du PD0 auf Low setzt,
hört die LED auf zu blinken, und du kannst mit PD1 und PD3 die
Blinkgeschwindigkeit einstellen. Wenn du PD0 wieder auf High setzt,
blinkt die LED mit der neuen geschwindigkeit.
Is das das was du beabsichtigst?"


Ja, genau dass sollte er tun, aber es funktioniert nicht.
Ich habe den kompletten Code des Programms nochmal in den
Anhang geladen.Dann könnt ihr nochmal drauf schauen,
wo der Fehler stecken könnte/was ich falsch gemacht habe.
Beim Compillieren bekomme ich auch keine Fehlermeldung,
wenn ich den Code in den Atmega8 lade, gehts nicht wie es soll.
Der Atmel läuft bei mir mit 8Mhz und als Optimierung habe ich
"-Os" eingestellt.

von Karl H. (kbuchegg)


Lesenswert?

muckelsoft wrote:

> Ja, genau dass sollte er tun, aber es funktioniert nicht.

Kannst du das präzisieren?
Was bedeutet: Funktioniert nicht.

So wie ich das sehe, musst du deine Steuerleitungen schon
eine ganze Weile auf 1 halten, damit du die freq Variable
hinreichend weit veränderst um eine Änderung der Blink-
frequenz sehen zu können.
Du hast in der Schleife eine Wartezeit von 30 ms. D.h. nach
1 Sekunde Steuereingang auf 1, hat sich die freq Variable
von 30 auf 60 erhöht. Das entspricht dann einer Abnahme der
Frequenz von 16Hz auf 8Hz.
Bei 33Hz solltest du als Normalsterblicher noch ev. ein Flimmern
der LED erkennen können, bei 8Hz ist das dann eher ein hektisches
Geflacker.

von Karl H. (kbuchegg)


Lesenswert?

Noch eine Frage:
Wie sieht bei dir die Beschaltung vom PORTD aus?
Sind da Taster oder sonstwas dran?

Grund der Frage: So wie du das in deinem Program hast,
ist das eher unüblich. Deine Taster sind laut Programm
high-side geschaltet. D.h. du musst am AVR Pin einen
Widerstand nach Masse haben, sowie einen Taster der den
Pin nach 5V zieht. Der Widerstand als Pull-Down Widerstand
ist absolut notwendig! Ansonsten weiss nur Gott alleine,
welchen Wert dein Port bei offenem Eingang meldet.

von muckelsoft (Gast)


Lesenswert?

@ kbuchegg:

An den Pins habe ich einen Taster, der diese mit 5Volt verbindet.
Hat bis jetzt bei anderen Projekten immer geklappt, deswegen
denk ich nicht das fehlende Widerstände die Ursache dafür sind, dass 
mein Programm nicht geht. Ich vermute den Fehler eher irgendwo im Code.
(Für den Fall das es doch am Widerstand liegen sollte, welchen
kOhm-Wert soll ich dranlöten?)

Mit "geht nicht" meine ich, dass ich zwar PD0 auf 5V legen kann
(Taster gedrückt) dann blinkt die LED. Drücke ich die Taster für
Wartezeit herauf/herab also PD1 oder PD3, hat das keinen Einfluss
auf auf die Blinkfrequenz (was es aber eigentlich haben sollte)
wenn ich danach wieder den PD0 Taster drücke...

von Falk B. (falk)


Lesenswert?

@ muckelsoft (Gast)

>An den Pins habe ich einen Taster, der diese mit 5Volt verbindet.

Und warum machst du es nciht wie alle anderen?

AVR-Tutorial: IO-Grundlagen

>Hat bis jetzt bei anderen Projekten immer geklappt, deswegen
>denk ich nicht das fehlende Widerstände die Ursache dafür sind, dass

DOCH!

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

muckelsoft wrote:
> @ kbuchegg:
>
> An den Pins habe ich einen Taster, der diese mit 5Volt verbindet.

OK. Was hängt am Eingang, wenn der Taster nicht gedrückt ist?

> Hat bis jetzt bei anderen Projekten immer geklappt, deswegen
> denk ich nicht das fehlende Widerstände die Ursache dafür sind, dass
> mein Programm nicht geht. Ich vermute den Fehler eher irgendwo im Code.
> (Für den Fall das es doch am Widerstand liegen sollte, welchen
> kOhm-Wert soll ich dranlöten?)

Nimm 10k. Der Wert ist nicht allzukritisch. Du kannst alles von
1k bis 1M benutzen, solange es nur den Pin bei nicht gedrücktem
Taster auf Masse zieht.

                   Vcc
                    |
                    |
                     /
                    /
                    |
     AVR -----------+
                    |
                   +-+
                   | | 10k
                   | |
                   +-+
                    |
                    |
                   GND

Ob das bei anderen Projekten geklappt hat oder nicht, spielt
keine Rolle. Wenn der Widerstand nicht da ist, hängt der
Eingang des AVR in der Luft und der fängt sich dort alles
möglich ein. Als ich meinen ersten Frequenzmesser mit einem
AVR baute, zeigte der am offenen Eingang, also ohne
dass irgendetwas an den Pin angeschlossen war, wunderbare
50Hz an. Rate mal wo die herkommen :-)

Oder aber du machst das ganze anders rum.
Den Taster schliesst du vom AVR-Pin nach Masse an.
Dann kannst du an diesem Port die im AVR eingebauten
Widerstände aktivieren und brauchst keine äusseren.

Einziger Unterschied: Per Programm stellst du eine 1
fest, wenn der Taster nicht gedrückt ist, und eine 0
wenn der Taster gedrückt ist.

Das ist dann eigentlich auch die übliche Art einen Taster
anzuschliessen, weil man sich dadurch die externen
Widerstände spart.

von muckelsoft (Gast)


Lesenswert?

@ kbuchegg:

Danke für die ausführliche Hilfestellung.
Hab den Pulldown Widerstand jetzt drangelötet
und siehe da, es funktioniert nun :)
Lag also demnach wirklich nur am Widerstand...

Danke nochmal an alle für die schnelle Hilfe.

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.