Forum: Mikrocontroller und Digitale Elektronik Variable übergeben in #include <avr/delay.h>


von __Son´s B. (bersison)


Lesenswert?

Hallo.
Ich möchte einen Piezo mit variabler Frequenzen und Dauer aus main() 
ansteuern.
Leider lässt delay.h folgenden Versuch nicht zu.

Wo ist der Denkfehler?
Und wie kann ich doch eine variable Zeit an delay.h übergeben?
1
#include <util/delay.h>
2
3
void Beep(unsigned int halbw, unsigned int interv)
4
{  unsigned int i;
5
  for(i=0; i<interv; i++)
6
  {  tog_bit(PORTB, PB2);
7
    _delay_us(halbw);
8
}}
9
10
int main(void) {
11
...
12
Beep(100, 1000);    // Halbwellenzeit, Signaldauer
13
... }

: Bearbeitet durch User
von Daniel R. (daro6)


Lesenswert?

Auch wenn ich dafür Timer nehmen würde kans du es so machen:
1
void varSleep(uint16_t microsekunden) {
2
    while(microsekunden--) 
3
         delay_us(1);
4
}
5
6
7
void Beep(unsigned int halbw, unsigned int interv) {  
8
    unsigned int i;
9
    for(i=0; i<interv; i++) {  
10
        tog_bit(PORTB, PB2);
11
        varSleep(halbw);
12
    }
13
}

Wobei du bei sehr kleinen Pausen den Einfluss der Wartschleife beachten 
musst.


Gruß,
Daniel

von W.A. (Gast)


Lesenswert?

__Son´s B. schrieb:
> Und wie kann ich doch eine variable Zeit an delay.h übergeben?

delay.h ist eine Header-Datei. An die wird gar nichts übergeben.

von Falk B. (falk)


Lesenswert?

@__Son´s Bersi__ (bersison)

>Ich möchte einen Piezo mit variabler Frequenzen und Dauer aus main()
>ansteuern.
>Leider lässt delay.h folgenden Versuch nicht zu.

Weil die Funktionen _delay_us() und _delay_ms() eingentlich Makros sind, 
die Konstanten brauchen.

>Wo ist der Denkfehler?
>Und wie kann ich doch eine variable Zeit an delay.h übergeben?

Gar nicht. Für us Zeiten nimmt man einen Timer mit Output Compare 
Funktion und CTC Modus. Die größeren Zeiten im Millisekundenbereich kann 
man eine Funktion schreiben.
1
void var_delay_ms(uint16_t milliseconds) {
2
    while(milliseconds--) 
3
         delay_ms(1);
4
}

Bei den Mikrosekunden funktioniert das nicht wirklich.

von __Son´s B. (bersison)


Lesenswert?

Folgendes habe ich probiert, komme aber absolut nicht auf die reelen 
us-Zeiten.

for(z=0; z<habw; z++)
{
tog_bit(PORTB, PB2);
_delay_us(1);
}

Bei Halbwelle 100us (5kHz) kommt durch unbekannte Verzugszeiten auf 
ca.1kHz.

von Karl M. (Gast)


Lesenswert?

Mit wie viel GHz läuft den Prozessor ?

von Thomas E. (thomase)


Lesenswert?

__Son´s B. schrieb:
> for(z=0; z<habw; z++)
> {
> tog_bit(PORTB, PB2);
> _delay_us(1);
> }

Der Ablauf dauert eben nicht n x 1µs, sondern n x die Zeit, die der 
gesamte Kladdatsch benötigt. Dann wird die Frequenz entsprechend 
kleiner.
Dieser Delay-In-Schleife-Trick funktioniert mit ms. Dabei bleibt der 
Schleifen-Overhead in einer erträglichen Toleranz. Für µs taugt das 
nichts. Jedenfalls nicht mit einer. Mit 100µs in der Schleife kann man 
auch noch leben.

Nimm einen Timer mit CTC.

mfg.

: Bearbeitet durch User
von Karl M. (Gast)


Lesenswert?

Hallo Son´s Bersi,

Ich habe die Firmware des "Parallax Serial LCD" auf Basis eines Atmega 
Attiny4313 nachprogrammiert und verwende für die Tonerzeugung zwei 
Timer.
Einer erzeugt per PWM einer der 12 Töne über 5 Oktaven, der andere 
steuert die Tondauer 1/1 Tonlänge = 2 Sekunden bis 1/64 Tonlänge.
Die Töne, mit allen ihren Parametern, werden über einen 75 Ton Fifo 
bereitgestellt. Die Tonausgabe mache ich über einen Piezo Schallwandler.

Die Anforderung dazu findet man hier:
# https://www.parallax.com/downloads/parallax-serial-lcd-product-guide
# https://www.parallax.com/product/27977

von W.A. (Gast)


Lesenswert?

__Son´s B. schrieb:
> Bei Halbwelle 100us (5kHz) kommt durch unbekannte Verzugszeiten auf
> ca.1kHz.

Das die Verzugszeiten unbekannt sind, liegt aber an dir. Guck dir den 
LST-File von deinem Compiler an und zähle die Prozessortakte für die 
Verwaltung zusammen. Und dann rechne mit der Prozessortaktfrequenz die 
zusätzliche Zeit aus.
Oder lass das Programm im Simulator mit Stopuhr laufen. Dann siehst du 
direkt, wo die Zeit bleibt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

__Son´s B. schrieb:
> Wo ist der Denkfehler?

Die Dokumentation nicht gelesen.

von __Son´s B. (bersison)


Lesenswert?

Guten Morgen und vielen Danke für eure Tips!

Wollte und werde ein flex. Low-Level-Pieper-Macro mit ATtiny85/1MHz 
herstellen, um zukünftig, Tastenquittierungen und Signalmeldungen 
schnell ein zu binden.

von delay (Gast)


Lesenswert?

@__Son´s Bersi__

Das Problem ist irgendwie gar nicht benannt. Was funktioniert denn 
nicht?

>Leider lässt delay.h folgenden Versuch nicht zu.

Schön, aber was heißt diese Aussage?

von __Son´s B. (bersison)


Lesenswert?

delay schrieb:
> Das Problem ist irgendwie gar nicht benannt.

Doch, mit _delay_us() kann keine Variable sondern nur eine konstante 
Zahl übergeben werden. Daher muss ich aus den oben genannten Tips, ein 
Lösung finden. Habe aber noch keine Zeit dazu gehabt...

von Karl H. (kbuchegg)


Lesenswert?

__Son´s B. schrieb:
> delay schrieb:
>> Das Problem ist irgendwie gar nicht benannt.
>
> Doch, mit _delay_us() kann keine Variable sondern nur eine konstante
> Zahl übergeben werden. Daher muss ich aus den oben genannten Tips, ein
> Lösung finden.

Ja. Und zwar nicht im kleinen µs Bereich. Verwaltung kostet auch Zeit. 
In deinem Fall die for Schleife. Die liegt in der Größenordnung weit 
über dem was du mit einem _delay_us(1) erreichen kannst.

Dein Dilemma ist also, dass momentan bildlich gesprochen 1 arbeitet und 
200 Leute die Arbeit verwalten. Das geht nun mal nicht gut.

In deinem Fall, wenn du einen Piezo als Lautsprecher ansteuern willst, 
ist die vernünftigste Lösung sowieso der Einsatz eines Timers, der den 
Pin ganz von alleine ansteuert. _delay_ms und _delay_us sind in realen 
Programmen selten die Lösung, oft aber das Problem.

: Bearbeitet durch User
von __Son´s B. (bersison)


Lesenswert?

Karl H. schrieb:
> In deinem Fall, wenn du einen Piezo als Lautsprecher ansteuern willst,
> ist die vernünftigste Lösung sowieso der Einsatz eines Timers, der den
> Pin ganz von alleine ansteuert.

Meinst du, statt uC als Tongenerator, einen NE555 (Bsp.) zu verwenden?

von Falk B. (falk)


Lesenswert?

@__Son´s Bersi__ (bersison)

>> In deinem Fall, wenn du einen Piezo als Lautsprecher ansteuern willst,
>> ist die vernünftigste Lösung sowieso der Einsatz eines Timers, der den
>> Pin ganz von alleine ansteuert.

>Meinst du, statt uC als Tongenerator, einen NE555 (Bsp.) zu verwenden?

NEIN! Er meint einen Timer IM Mikrocontroller!

von Karl H. (kbuchegg)


Lesenswert?

Falk B. schrieb:
> @__Son´s Bersi__ (bersison)
>
>>> In deinem Fall, wenn du einen Piezo als Lautsprecher ansteuern willst,
>>> ist die vernünftigste Lösung sowieso der Einsatz eines Timers, der den
>>> Pin ganz von alleine ansteuert.
>
>>Meinst du, statt uC als Tongenerator, einen NE555 (Bsp.) zu verwenden?
>
> NEIN! Er meint einen Timer IM Mikrocontroller!


Genau.
Das hier
FAQ: Timer

von __Son´s B. (bersison)


Lesenswert?

> Er meint einen Timer IM Mikrocontroller!

Ok, habe mich eingelesen.
Scheint mir aufwendiger, als mit _delay_us() zu arbeiten - aber 
wesentlich effektiver.

DANKE!

von Falk B. (falk)


Lesenswert?

@__Son´s Bersi__ (bersison)

>> Er meint einen Timer IM Mikrocontroller!

>Ok, habe mich eingelesen.
>Scheint mir aufwendiger, als mit _delay_us() zu arbeiten - aber
>wesentlich effektiver.

Wenn  dir das Einstellen einer handvoll von Bits in 1-3 Registern zu 
aufwändig ist, solltest du dir ein anderes Hobby suchen.

von Walter S. (avatar)


Lesenswert?

Falk B. schrieb:
>>Ok, habe mich eingelesen.
>>Scheint mir aufwendiger, als mit _delay_us() zu arbeiten - aber
>>wesentlich effektiver.
>
> Wenn  dir das Einstellen einer handvoll von Bits in 1-3 Registern zu
> aufwändig ist, solltest du dir ein anderes Hobby suchen.

du bist etwas demotivierend, der TO scheint doch nicht so lernresistent 
wie manche hier, was will man denn mehr von einem Anfänger.

von hauspapa (Gast)


Lesenswert?

__Son´s B. schrieb:
> Bei Halbwelle 100us (5kHz) kommt durch unbekannte Verzugszeiten auf
> ca.1kHz.

__Son´s B. schrieb:
> Low-Level-Pieper-Macro mit ATtiny85/1MHz

Wieviel Takt muss
_delay_us(1) bei 1MHz verbraten?

wieviel sind es real:
Statt 5kHz nur 1kHz beutet der Comiler schafft die ganze Schleife mit 
Vergleich und allem drum und dran innerhalb von 5 Taktzyklen. Ich hätte 
dem Kerl garnicht zugetraut das er das so effizient kann.

Wenn die Anzahl unterschiedlicher Tonlängen gering ist, kannst Du 
natürlich auch für jede Tonlänge ein eigenes _delay_us(XY) mit festem 
Parameter anlegen und entsprechend aufrufen wenn die Tonlänge gerade 
dran ist.

viel Erfolg
hauspapa

von __Son´s B. (bersison)


Lesenswert?

hauspapa schrieb:
> Wenn die Anzahl unterschiedlicher Tonlängen gering ist, kannst Du
> natürlich auch für jede Tonlänge ein eigenes _delay_us(XY) mit festem
> Parameter anlegen und entsprechend aufrufen wenn die Tonlänge gerade
> dran ist.

Hi!
So ähnlich habe ich es vorerst gemacht, allerdings in 50us-Schritten, 
die ich nur wenige mal in eigener Schleife summiere.
Somit ist eine einfacher Tonhöhen-Crescendo möglich.
"Timer"-Lösungen kommen später.

hauspapa schrieb:
> wieviel sind es real:
> Statt 5kHz nur 1kHz beutet der Comiler schafft die ganze Schleife mit
> Vergleich und allem drum und dran innerhalb von 5 Taktzyklen.

Passender CPU-Speed ist für mich noch ein Buch mit 7 Siegeln.
Als Anfänger, erst einmal einige Ideen ans Laufen bekommen und den 
FRANZIS-Leitfaden ab arbeiten.

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.