Variable übergeben in #include <avr/delay.h>

#4369360
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
... }
#4369373
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
#4369380
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.
#4369409
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.
Gast #4369414
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
Gast #4369425
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.
#4369930
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.
#4370210
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!
#4370238
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
#4370552
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.
#4370579
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.
Gast #4370603
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
#4371561
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren