Forum: Mikrocontroller und Digitale Elektronik Piezo mit unterschiedlichen Tönen


von Tho W. (tommyprog)


Angehängte Dateien:

Lesenswert?

Servus,

auch ich habe ein Problem mit einen Piezo- Lautsprecher. Aufgrund des
Problems habe ich wegen der Lautstärke hier einfach mal gepostet, bitte
nicht aufregen^^

Zuerst einmal:

                                   Hardware:

- myAVR Board Mk2 mit einen Piezo Lautsprecher (aus den myAVR
Einsteigerset) mit einen Atmel ATmega8
- dieses Board ist mit einen selbstgebautem Adapterkabel (anstelle der
grünen Platine) mit einen
AVRISP MK2 Programmer verbunden
- Der Programmer ist über ein USB Kabel mit den Rechner verbunden
- Entwicklungsumgebung ist das Atmel Studio 6
- Konstat- Spannungsversorgung: Voltcraft DPS-4005PFC 9.01V, 0.009A im
Idle


                                    Aufgabenstellung:

- Wenn Taster 1 gedrückt wird, kommmt der Ton A mit 440Hz aus den Piezo-
Lautsprecher. Solange, bis Taster 2 gedrückt wird, denn dann kommt Ton C
mit 263Hz aus den Lautsprecher.

Dies soll solange passieren, bis beide Taster gleichzeitig gedrückt
werden, dann passiert nichts, und man hört kein gepiepse mehr.

                                      Meine Lösung:

- per ATmel Studio 6 habe ich 3 Cases gemacht. (s. kleiner Code im
Anhang)
- Für die Taster habe ich die Debounce- Methode vom PeDa übernommen
- nun habe ich nochmals per myAVR Lehrbuch eine wait- Funktion
implementiert, die scheinbar noch nicht so ausgereift ist, d.h. PROBLEM!

PRoblem detailiert: Drücke ich Taster 1 kommt ein Ton. --> ok
- Drücke ich Tatser 2 kommt derselbe Ton. -->NOK
- Drücke ich beide Taster gleichzeitig, kommt immernoch derselbe Ton
-->NOK

Hierbei bröchte ich bitte Tipps, was ich falsch gemacht habe.
Hinweise auf Entprellen, PWM oder Interrupts möchte ich nicht. Ich würde
es gerne auf die Art lösen, bin fast am Ziel, nur irgendwo hängt er.
Meine Vermutung ist, dass er einfach nicht in eine Schleife reinkommt,
in der er die Frequenz für den Ton entsendet.

Danke. Mfg,
tommyProg

von Max B. (theeye)


Lesenswert?

Hallo!

Tho Wes schrieb:
> Meine Vermutung ist, dass er einfach nicht in eine Schleife reinkommt,
> in der er die Frequenz für den Ton entsendet.

Warum klappt dann das Ausstellen des Tons auch nicht?


Die Ton-Funktionen habe ich mir noch nicht angeguckt. Was mir jedoch 
direkt aufgefallen ist:

1. Sicher, dass du keine *.c-Datei erstellen möchtest?
2. Du nutzt bereits eine Debounce Funktion von Peter Dannegger. Warum 
nutzt du nicht die Timer-Variante und nutzt hier die Funktionen 
get_key_press (heißt sie glaube ich) und die Funktion für das pressen 
aller Taster (Name weiß ich gerade nicht)? Das ganze in einer 
while-Schleife mit entsprechenden if Abfragen und den dazugehörigen 
Funktionsaufrufen zur Tonerzeugung und fertig.
3. Wenn du Code von anderen Leuten übernimmst, ist dieser zu 
kennzeichnen! Erst recht, wenn du diesen Code dann so öffentlich 
präsentierst. Das gilt umso mehr, wenn es sich um Code von Leuten 
handelt, die sich extra die Mühe gemacht haben dazu noch eine Anleitung 
zu schreiben...

Gruß Max

P.S.: Wenn du die Timer-Variante nicht nehmen möchtest, übernehme die 
Idee bzgl. der genannten Funktionen.

von Tho W. (tommyprog)


Lesenswert?

Max B. schrieb:
> Hallo!
>
> Tho Wes schrieb:
>> Meine Vermutung ist, dass er einfach nicht in eine Schleife reinkommt,
>> in der er die Frequenz für den Ton entsendet.
>
> Warum klappt dann das Ausstellen des Tons auch nicht?
Zum Ausstellen des Tons habe ich garnichts gesagt gehabt- Das hatte ich 
vergessen.
Das Ausstellen funktioniert, wenn ich beide Taster gedrückt halte.



> Die Ton-Funktionen habe ich mir noch nicht angeguckt. Was mir jedoch
> direkt aufgefallen ist:
> 1. Sicher, dass du keine *.c-Datei erstellen möchtest?

Ja, da bin ich mir sicher.

> 2. Du nutzt bereits eine Debounce Funktion von Peter Dannegger. Warum
> nutzt du nicht die Timer-Variante
Weil ich mich für Kapitel um Kapitel einarbeiten muss, und ich jetzt 
erst (vor 30 Minuten mit Timer einarbeiten begonnen habe)
Für dieses Problem muss ich noch so eine Art und weiße benutzen.

und nutzt hier die Funktionen
> get_key_press (heißt sie glaube ich) und die Funktion für das pressen
> aller Taster (Name weiß ich gerade nicht)?
Weil ich auch eigene geschrieben habe. (nur die Debounce nicht)

Das ganze in einer
> while-Schleife mit entsprechenden if Abfragen und den dazugehörigen
> Funktionsaufrufen zur Tonerzeugung und fertig.
Habe ich mir auch so in der richtung gedacht, haut aber net so ganz hin.
meine while- schleife ist eher ein switch-case

> 3. Wenn du Code von anderen Leuten übernimmst, ist dieser zu
> kennzeichnen! Erst recht, wenn du diesen Code dann so öffentlich
> präsentierst. Das gilt umso mehr, wenn es sich um Code von Leuten
> handelt, die sich extra die Mühe gemacht haben dazu noch eine Anleitung
> zu schreiben...
>
Da stimm ich dir zu. Entschuldigung, hätte ich kennzeichnen müssen. 
Versuche es für die Zukunft zu kennzeichnen.

von Johannes R. B. (Gast)


Lesenswert?

hier mal meine Lösung LOL
1
//----------------------------------------------------------------------
2
// Titel     : Beispiel zwei Töne
3
//----------------------------------------------------------------------
4
// Funktion  : T1->440Hz Kammerton A, T2->263Hz Kammerton C
5
// Schaltung : Taste1=D2, Taste2=D3, Speaker=B1
6
//----------------------------------------------------------------------
7
// Prozessor : ATmega8
8
// Takt      : 3686400
9
// Sprache   : myAVR C++
10
//----------------------------------------------------------------------
11
class Application : public Controller
12
{
13
    protected: SoundChanelA sound;
14
    protected: Button button1;
15
    protected: Button button2;
16
    
17
    
18
    public: void onStart()
19
    {
20
    button1.config(portD,bit2); 
21
    button2.config(portD,bit3);
22
       
23
    }
24
    
25
    public: void onWork()
26
    {
27
    // leer    
28
      if (button1.isPressed() && button2.isPressed())
29
        sound.stop();
30
    
31
    
32
    }
33
    
34
    public: void onEvent(const Object& sender, uint8 data)
35
    {
36
      // Kammerton A
37
      if (sender==button1 && data==Button::Click )
38
      sound.play(FLASHSTR("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));      
39
      
40
      // Kammerton C
41
      if (sender==button2 && data==Button::Click )
42
      sound.play(FLASHSTR("ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"));      
43
    
44
      // alle meine Entchen :-D
45
      if (sender==button1 && data==Button::HoldStart )
46
      sound.play(FLASHSTR("v d,e,f,g,aa,aa, h,h,h,h,aa,.. h,h,h,h,aa,.. g,g,g,g,ff,ff, a,a,a,a,dd"));      
47
   
48
      // der imperiale Marsch :-o
49
      if (sender==button1 && data==Button::HoldStart )
50
      sound.play(FLASHSTR("vfff,,fff,,fff,,dd,a,ff.dd,a,ffff..CCC,,CCC,,CCC,,DD,C,ff.dd,a,ffff..."));
51
       }
52
   
53
   
54
} app;

lg

von Tho W. (tommyprog)


Lesenswert?

>
> } app;
> [/c]
>
> lg

Danke dir, die idee ist cool, aber ich kann aufgrund meiner 
"profikenntnisse" deinen code nahezu garnicht lesen. Ich lerne das ganze 
noch, wie z.b. eine Klasse usw. aufgebaut ist, aber nun muss ich die 
Timer erst hinter mir bringen, und dann kommen noch die PWM's mit den 
UART..

Weist du vielleicht, was bei mir falsch sein könnte?

Mfg,
TommyProg

von Johannes R. B. (Gast)


Lesenswert?

tja... für mich ist dein code ziemlich schlecht verständlich :-(
zunächst mal würde ich beim flüchtig drüber schauen sagen dass sich 
deine Bedinungen gegenseitig ausschließen
1
if((debounce(PIND,TASTER_2))&&(taster_was_pressed(TASTER_2)))
2
...
3
else if(((debounce(PIND,TASTER_1))&&(taster_was_pressed(TASTER_1)))&&((debounce(PIND,TASTER_2))&&(taster_was_pressed(TASTER_2))))

das Abfragen von Taster2 verhindert bei der Bauweise dass er je zur 
Abfrage Taster1&&Taster2 kommt ... des weiteren verändern deine 
Funktionen zumindest beim drücken der Tasten potentiell deine Töne da du 
die Frequenz mit wartezyklen aufbaus... und noch eins ... 1us sind bei 
3,6864 Mhz etwa 3 Takte ... ich denk mal die for-schleife drum rum und 
der Funtionsaufruf/Makro-Overhad verbrauchen schon ein vielfaches ... 
deswegen kommt irgendwie immer ein ton der nix mit dem Kammerton A oder 
C zu tun hat

wie gesagt nur so vom flüchtig drüber schauen ... ansonsten ist mir die 
C-Schreibweise etwas zu kryptisch ;-)

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Debouncen ist in diesem Fall gar keine so gute Idee.
Das Problem ist so gestellt, dass du auch nicht Debouncen brauchst. Es 
reicht völlig aus, wenn du feststellst, ob eine Taste niedergedrückt 
wurde und wenn ja, dann schaltest du den Modus in deinem Programm um 
(Ton A, Ton B, kein Ton).
Das Problem ist nämlich, dass du es kaum schaffen wirst, beide Tasten in 
exakt den paar µs gleichzeitig zu drücken, die notwendig wären, damit 
das Programm beide Tasten als gedrückt bemerkt. Immer daran denken: 
Debouncen heisst auch, dass dein Programm nur ein einziges mal die 
Benachrichtigung bekommt, dass eine Taste gedrückt wurde. Ein einziges 
mal! Danach kann die Taste immer noch gedrückt sein, dass interessiert 
den Code nicht wirklich.

In deinem Beispiel brauchst du das aber auch gar nicht. Wenn dein 
Programm aufgrund eines Tastendrucks in einen Modus wechselt (welcher 
Ton soll gespielt werden, wenn überhaupt), dann bewirkt ein weiterer 
Tastendruck nichts mehr weiter. Der Modus wird erst dann gewechselt, 
wenn eine andere Taste gedrückt wird. Die Tasten verriegeln sich in der 
Aufgabenstellung quasi gegenseitig. Es ist daher völlig unerheblich, ob 
die Tasten prellen oder nicht. Es ist auch völlig unerheblich, ob du den 
Tastendruck erkennst, oder ob eine gedrückte Taste. Denn wieder: Wird 
eine Taste 8-tausend mal als gedrückt erkannt, dann spielt das keine 
Rolle. Wird aufgrund der TASTE_1 bereits der erste Ton gespielt, dann 
kann die Taste 8-tausend mal in diesen Modus schalten, das verändert 
nichts - denn der Ton wird ja bereits gespielt.

Als erster Ansatzpunkt:
1
#define KEIN_TON   0
2
#define TON_A      1
3
#define TON_B      2
4
5
6
....
7
8
  Modus = KEIN_TON;
9
10
  while( 1 ) {
11
12
    // Auswerten der Tasten
13
    // Welche Tasten sind gedrückt?
14
15
    if( PIND & ( 1 << TASTER_1 ) )
16
      Modus = TON_A;
17
18
    if( PIND & ( 1 << TASTER_2 ) )
19
      Modus = TON_B;
20
21
    if( ( PIND & ( 1 << TASTER_1 ) ) &&
22
        ( PIND & ( 1 << TASTER_2 ) ) )
23
      Modus = KEIN_TON;
24
25
    // Auswerten des MOdus, in dem das Programm gerade ist
26
    if( Modus == TON_A ) {
27
      PORTB ^= Lautsprecher_an;
28
      _delay_ms( .... Zeit für eine Halbwelle bei 440Hz ... );
29
    }
30
31
    else if( Modus == TON_B ) {
32
      PORTB ^= Lautsprecher_an;
33
      _delay_ms( .... Zeit für eine Halbwelle bei 263Hz ... );
34
    }
35
36
  }
37
}

Ein Problem bleibt noch.
Und zwar wird es dir kaum gelingen, beide Tasten (wenn sie gleichzeitig 
gedrückt wurden) absolut gleichzeitig loszulassen. Drückst du beide 
Tasten, dann wird zwar der Ton korrekt verstummen. Aber wenn du die 
beiden Tasten loslässt, wirst du mit irgendeinem Finger hinterherhinken 
und das Programm wird die verbliebene Taste als gedrückt werten. Da 
musst du dir noch was einfallen lassen. (Zum Beispiel, dass der Modus 
KEIN_TON erst dann wieder verlassen werden kann, wenn beide Tasten nicht 
gedrückt sind. Das könnte man zb erreichen, indem man einen 4.ten 
Zustand WARTEND einführt. Der Wechsel in den Zustand TON_A kann nur dann 
erfolgen, wenn das Programm im Zustand WARTEND ist. Genauso bei TON_B. 
Aus dem Zustand KEIN_TON kommt man nur dann in den Zustand WARTEND, wenn 
beide Tasten nicht gedrückt sind.


-> du bist auf dem Weg zu einer Technik, die man Zustandsmaschine (oder 
engl. Statemachine) nennt. Eine sehr fruchtbare Technik.

von Tho W. (tommyprog)


Lesenswert?

@Johannes R. B. (Gast)
> das Abfragen von Taster2 verhindert bei der Bauweise dass er je zur
> Abfrage Taster1&&Taster2 kommt ... des weiteren verändern deine
> Funktionen zumindest beim drücken der Tasten potentiell deine Töne da du
> die Frequenz mit wartezyklen aufbaus... und noch eins ... 1us sind bei
> 3,6864 Mhz etwa 3 Takte ... ich denk mal die for-schleife drum rum und
> der Funtionsaufruf/Makro-Overhad verbrauchen schon ein vielfaches ...
> deswegen kommt irgendwie immer ein ton der nix mit dem Kammerton A oder
> C zu tun hat

Danke Dir. Werde versuchen dies zu verbessern.
Was die 3.6864Mhz betrifft, so habe ich aber nach wie vor intern die 
1Mhz am laufen.

Mit den Atmel Studio 6 und meinen AVR ISP MK2 bin ich dabei die 1mhz auf 
den externen QUARZ auf 3.6864 zu ändern.

Hierzu würde ich folgendes anklicken:

EXTRCOSC_OMH29_3MHZ_18CK_64MS (in der Zeile meines ATMEL STudio 6 bei 
Fuses programmieren.)
Es handelt sich um einen "KD0823" QUARZ. Im Datenblatt vom ATmega8 habe 
ich unter "external crystal" leider nichts gefunden.

Stimmt aber mein Vorschlag mit der zuvor geschriebenenen 
Fußeprogrammierung?

mfg,
tommyProg

: Bearbeitet durch User
von Tho W. (tommyprog)


Lesenswert?

Karl Heinz schrieb:
> Debouncen ist in diesem Fall gar keine so gute Idee.
> Das Problem ist so gestellt, dass du auch nicht Debouncen brauchst. Es
> reicht völlig aus, wenn du feststellst, ob eine Taste niedergedrückt
> wurde und wenn ja, dann schaltest du den Modus in deinem Programm um
> (Ton A, Ton B, kein Ton).

Ah okay. Dann frage ich ab, ob der Taster gedrückt worden ist.
Aber erst wenn der Taster wieder losgelassen wird, soll er in den 
Zustand wechseln.

> Das Problem ist nämlich, dass du es kaum schaffen wirst, beide Tasten in
> exakt den paar µs gleichzeitig zu drücken,
Das ist war, würde auch den Fall erklären, warum ich mit beiden Tastern 
gleichzeitig mein Programm nicht beenden kann.

>die notwendig wären, damit
> das Programm beide Tasten als gedrückt bemerkt. Immer daran denken:
> Debouncen heisst auch, dass dein Programm nur ein einziges mal die
> Benachrichtigung bekommt, dass eine Taste gedrückt wurde. Ein einziges
> mal! Danach kann die Taste immer noch gedrückt sein, dass interessiert
> den Code nicht wirklich.
Okay, aber wenn die Taste dann noch gedrückt ist, und ich erst den 
Zustand ändere ,wenn mein Finger von der Taste runtergeht, brauche ich 
im Programm theorteisch eine Funktion, die Abfrägt, ob nun der Finger 
wirklich von der Taste unten ist.


> In deinem Beispiel brauchst du das aber auch gar nicht. Wenn dein
> Programm aufgrund eines Tastendrucks in einen Modus wechselt
 Entschuldige, hätte sagen sollen, wenn die Taste gedrückt worden ist, 
und der Finger von der taste ist.

>(welcher
> Ton soll gespielt werden, wenn überhaupt), dann bewirkt ein weiterer
> Tastendruck nichts mehr weiter. Der Modus wird erst dann gewechselt,
> wenn eine andere Taste gedrückt wird. Die Tasten verriegeln sich in der
> Aufgabenstellung quasi gegenseitig.
Oh, danke für die information.

>Es ist daher völlig unerheblich, ob
> die Tasten prellen oder nicht. Es ist auch völlig unerheblich, ob du den
> Tastendruck erkennst, oder ob eine gedrückte Taste. Denn wieder: Wird
> eine Taste 8-tausend mal als gedrückt erkannt, dann spielt das keine
> Rolle. Wird aufgrund der TASTE_1 bereits der erste Ton gespielt, dann
> kann die Taste 8-tausend mal in diesen Modus schalten, das verändert
> nichts - denn der Ton wird ja bereits gespielt.
>
> Als erster Ansatzpunkt:
>
>
1
> 
2
> #define KEIN_TON   0
3
> #define TON_A      1
4
> #define TON_B      2
5
> 
6
> 
7
> ....
8
> 
9
>   Modus = KEIN_TON;
10
> 
11
>   while( 1 ) {
12
> 
13
>     // Auswerten der Tasten
14
>     // Welche Tasten sind gedrückt?
15
> 
16
>     if( PIND & ( 1 << TASTER_1 ) )
17
>       Modus = TON_A;
18
> 
19
>     if( PIND & ( 1 << TASTER_2 ) )
20
>       Modus = TON_B;
21
> 
22
>     if( ( PIND & ( 1 << TASTER_1 ) ) &&
23
>         ( PIND & ( 1 << TASTER_2 ) ) )
24
>       Modus = KEIN_TON;
25
> 
26
>     // Auswerten des MOdus, in dem das Programm gerade ist
27
>     if( Modus == TON_A ) {
28
>       PORTB ^= Lautsprecher_an;
29
>       _delay_ms( .... Zeit für eine Halbwelle bei 440Hz ... );
30
>     }
31
> 
32
>     else if( Modus == TON_B ) {
33
>       PORTB ^= Lautsprecher_an;
34
>       _delay_ms( .... Zeit für eine Halbwelle bei 263Hz ... );
35
>     }
36
> 
37
>   }
38
> }
39
>
Danke, das mit den Modusabfragen scheint eine gute idee zu sein, werde 
mich nach den Quarz- Problem mit den Beschäftigen.



> Ein Problem bleibt noch.
> Und zwar wird es dir kaum gelingen, beide Tasten (wenn sie gleichzeitig
> gedrückt wurden) absolut gleichzeitig loszulassen. Drückst du beide
> Tasten, dann wird zwar der Ton korrekt verstummen. Aber wenn du die
> beiden Tasten loslässt, wirst du mit irgendeinem Finger hinterherhinken
> und das Programm wird die verbliebene Taste als gedrückt werten. Da
> musst du dir noch was einfallen lassen. (Zum Beispiel, dass der Modus
> KEIN_TON erst dann wieder verlassen werden kann, wenn beide Tasten nicht
> gedrückt sind. Das könnte man zb erreichen, indem man einen 4.ten
> Zustand WARTEND einführt. Der Wechsel in den Zustand TON_A kann nur dann
> erfolgen, wenn das Programm im Zustand WARTEND ist. Genauso bei TON_B.
> Aus dem Zustand KEIN_TON kommt man nur dann in den Zustand WARTEND, wenn
> beide Tasten nicht gedrückt sind.
Wenn ich das als Zwischenzustand verstehe, könnte man über eine interne 
Countervariable einen Wert belegen und abfragen, ob es schon gedrückt 
worden ist.


>
> -> du bist auf dem Weg zu einer Technik, die man Zustandsmaschine (oder
> engl. Statemachine) nennt. Eine sehr fruchtbare Technik.

In Theoretische Informatik hatten wir das schonmal als Zustandsautomat 
behandelt. Gut, dass die Technik auch hier anwendbar ist.

mfg, TommyProg

von Possetitjel (Gast)


Lesenswert?

Johannes R. B. schrieb:

> {
>       // Kammerton A
>       if (sender==button1 && data==Button::Click )

Hmmm.

>       // Kammerton C
>       if (sender==button2 && data==Button::Click )

Es gibt keinen "Kammerton C".

Es gibt höchstens noch den Kirchenton (Chorton) und den
Cornettton.

>       // alle meine Entchen :-D
>       if (sender==button1 && data==Button::HoldStart )
>       sound.play(FLASHSTR("v d,e,f,g,aa,aa, h,h,h,h,aa,.. h,h,h,
>       h,aa,..  g,g,g,g,ff,ff, a,a,a,a,dd"));

Hier handelt es sich - je nach Sichtweise - um ein musikalisches
Verbrechen bzw. einen musikalischen Geniestreich: Die Wiedergabe
des allbekannten Volksliedes "Alle meine Entchen" in der Kirchen-
tonart "Dorisch".

Nun ja. :)

von Tho W. (tommyprog)



Lesenswert?

@Karl Heinz

Du hattest recht, das Debouncen konnte man rausnehmen.
Nun habe ich das Problem mit Interrupts von Schaltern gelöst.- Jedoch 
kann ich nichtmehr ausschalten und die Frequenzen sind gleich.

Mit einen Steuerungsflag frage ich den entsprechenden Zustand ab (s. 
Code).
Leider ist die Lautstärke meines Lautsprechers nahezu gleich, oder ist
263Hz und 440Hz nahezu für das menschliche Ohr kaum zu unterscheiden?

Mit freundlichen Grüßen,
TommyProg

von Possetitjel (Gast)


Lesenswert?

Tho Wes schrieb:

> Leider ist die Lautstärke meines Lautsprechers nahezu gleich,
> oder ist 263Hz und 440Hz nahezu für das menschliche Ohr kaum
> zu unterscheiden?

Wovon sprichst Du?

"Frequenz" ("Hertz (Hz)") ist ein Maß für die Tonhöhe. Das
hat mit der Lautstärke nix zu tun. - Dagegen ist Lautstärke
eben Lautstärke.

von Tho W. (tommyprog)


Lesenswert?

Possetitjel schrieb:
> Tho Wes schrieb:
>
>> Leider ist die Lautstärke meines Lautsprechers nahezu gleich,
>> oder ist 263Hz und 440Hz nahezu für das menschliche Ohr kaum
>> zu unterscheiden?
>
> Wovon sprichst Du?
>
> "Frequenz" ("Hertz (Hz)") ist ein Maß für die Tonhöhe. Das
> hat mit der Lautstärke nix zu tun. - Dagegen ist Lautstärke
> eben Lautstärke.

-> Frequenzen werden bis 15Hz als Blinken wargenommen (Zitat aus myAVR 
Lehrbuch).
Was die Tonhöhe angeht, ist das menschliche Ohr eingeschränkt.
Ich möchte wissen, ob man akustisch 263Hz von 440Hz unterscheiden 
möchte.

Ob ich wissen will, ob ich die Lautstärke unterscheiden will, ahbe ich 
nie gesagt^^. Nur die Frequenz möchte ich wissen.
mfg

von Dietrich L. (dietrichl)


Lesenswert?

Tho Wes schrieb:
> oder ist
> 263Hz und 440Hz nahezu für das menschliche Ohr kaum zu unterscheiden?

Wenn das so wäre, würden alle Musiker arbeitslos :-((
Schau mal hier:
http://de.wikipedia.org/wiki/Frequenzen_der_gleichstufigen_Stimmung

Gruß Dietrich

von Possetitjel (Gast)


Lesenswert?

Tho Wes schrieb:

> -> Frequenzen werden bis 15Hz als Blinken wargenommen (Zitat
> aus myAVR Lehrbuch).

Lehrbuch wegwerfen! (Oder aufmerksamer lesen!)

Wenn Du an einen Lautsprecher 15Hz anlegst, nimmst Du ganz
bestimmt kein Blinken wahr!

Wenn Du im Gegenzug an eine Leuchtdiode 1000Hz anlegst, hörst
Du (i.d.R.) auch keinen Ton!

> Was die Tonhöhe angeht, ist das menschliche Ohr eingeschränkt.
> Ich möchte wissen, ob man akustisch 263Hz von 440Hz unterscheiden
> möchte.

Machst Du Witze?!

Mit einem Minimum an Übung kann man auch 263Hz von 270Hz unterscheiden,
wenn die Töne nacheinander erklingen.

263Hz und 440Hz liegen deutlich weiter auseinander als das "Ta" und
das "Tü" beim klassischen "Tatü-Tata" der Feuerwehr.

Es gibt aber ein ganz anderes Problem: Die Signale, die ein µC
erzeugen kann, sind i.d.R. Rechtecksignale mit vielen Oberwellen.
Ein Piezo hat häufig einen sehr schlechten Frequenzgang. Es kann
also sein, dass die Töne sehr stark verfälscht wiedergegeben werden
und dadurch schlechter unterscheidbar sind.
Du kannst das Intervall probeweise kleiner wählen, also z.B.
260Hz und 320Hz. Das ist akustisch immer noch deutlich zu
unterscheiden.

> Ob ich wissen will, ob ich die Lautstärke unterscheiden will, ahbe
> ich nie gesagt^^. Nur die Frequenz möchte ich wissen.

Ohne Dir zu nahe treten zu wollen: Ich war nicht sicher, ob Dir
der physikalische Unterschied zwischen Lautstärke und Frequenz
überhaupt klar ist.

von Karl H. (kbuchegg)


Lesenswert?

Tho Wes schrieb:

> 263Hz und 440Hz nahezu für das menschliche Ohr kaum zu unterscheiden?

Wenn dir das nicht klar ist, dann solltst du ein Experiment machen.
Taschenrechner hernehmen und mal ausrechnen, in welchen Zeitabständen du 
einen Pin toggeln musst, damit du 440Hz kriegst

Ich nehm mal den Taschenrechner und rechne
1/440 = 0.00227.  Das sind 2.27 Millisekunden

1/263 = 0.00380.  Das sind 3.80 Millisekunden

Da der Pin getoggelt wird, brauchst du die Hälfte der Zeit. Denn die 
Hälfte der Zeit ist der Pin ja auf 0 und die andere Hälft auf 1. Beides 
zusammen muss zb 2.27 Millisekunden dauern, damit du deine 440Hz 
kriegst.

Und das probierst du jetzt einfach mal aus
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
#define DELAY_TIME 1.135    // für 440 Hz
7
// #define DELAY_TIME  1.90   // fuer 263 Hz
8
9
int main()
10
{
11
  DDRB |= ( 1 << PB1 );
12
13
  while( 1 ) {
14
    PORTB |= ( 1 << PB1 );
15
    _delay_ms( DELAY_TIME );
16
17
    PORTB &= ~( 1 << PB1 );
18
    _delay_ms( DELAY_TIME );
19
  }
20
}


Compilier das Programm, korrigiere Tippfehler die ich gemacht habe, lass 
es laufen und hör dir den Unterschied zwischen 440Hz und 263Hz an. Ganz 
genau werden die Frequenzen nicht stimmen, aber das macht nichts. Ob das 
jetzt exakt 440Hz sind, oder 439 oder 441, spielt keine wirkliche Rolle, 
wenn es darum geht, den Unterschied zu 263Hz zu hören (die auch keine 
263Hz sein werden, sondern vielleicht 262 oder 264 oder irgendwas 
dazwischen).
Das Programm ist einfach genug, dass es kaum eine Möglichkeit gibt, 
einen Fehler zu machen.
Das sind also die beiden Töne. Wenn dein Programm die nicht produziert, 
dann hast du schlicht und ergreifend eine Fehler im Programm.

Weiter werd ich mich nicht äussern, bis auf eine Ausnahme. Hat ja 
sowieso keinen Zweck, du baust ja sowieso alles anders auf, als man es 
dir zeigt, mit dem Effekt, dass dann nichts funktioniert.

Die Ausnahme:
Das hier
1
  double endwert= (1/frequenz);
macht nicht das was du denkst was es tut.

FAQ: Datentypen in Operationen


Du machst den Kardinalfehler aller Neulinge: Du schreibst zuviel Code 
auf einmal, den du dann nicht gebacken kriegst und von dem du nicht 
weißt wo die Fehler sein könnten. Fang mit einfachen Programmen an! So 
wie das Beispiel hier, in dem erst mal auf jeglichen Schnickschnack mit 
Tasten verzichtet wird und es einfach nur darum geht einen Ton zu 
produzieren. Durch Umkommentieren produziert es einen anderen Ton. Das 
ist so ziemlich die einfachste Variante, mit der du anfangen kannst und 
es gibt so gut wie nichts, was dabei schief gehen kann, ausser dass du 
den falschen Pin erwischt, dass die angegebene Taktfrequenz des 
Prozessors nicht stimmt, du vergessen hast, den Optimizer einzuschalten 
oder der Lautsprecher (Piezo) bei genau diesen Frequenzen eine 
mieserablen Wirkungsgrad hat. Aber abgesehen davon kann nicht wirklich 
was dabei schief gehen und du hast erst mal ein Programm mit dem du dich 
davon überzeugen kannst, dass du 2 verschiedene Töne produzieren kannst. 
Und erst DANN fängst du an, Komplexität ins Programm mit hineinzunehmen. 
Wobei du auch nicht gleich in die vollen gehst, sondern Schrittweise an 
die Sache herangehst. Dein nächstes Ziel könnte zb sein, mit einer Taste 
zwischen den beiden Tönen umzuschalten. Nicht mehr!
Das ist aber simpel
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
#define DELAY_TIME_1  1.135    // für 440 Hz
7
#define DELAY_TIME_2  1.90   // fuer 263 Hz
8
9
int main()
10
{
11
  DDRB |= ( 1 << PB1 );
12
13
  // Pullup für den Taster
14
  PORTD |= ( 1 << PD2 );
15
16
  while( 1 ) {
17
    PORTB |= ( 1 << PB1 );
18
19
    if( PIND & ( 1 << PD2 ) )
20
      _delay_ms( DELAY_TIME_1 );
21
    else
22
      _delay_ms( DELAY_TIME_2 );
23
24
25
    PORTB &= ~( 1 << PB1 );
26
27
    if( PIND & ( 1 << PD2 ) )
28
      _delay_ms( DELAY_TIME_1 );
29
    else
30
      _delay_ms( DELAY_TIME_2 );
31
  }
32
}

Die Modifikation ist simpel und leicht zu prüfen. Vom ersten Programm 
hast du noch die unterschiedlichen Tonhöhen im Ohr. Genau die müssen 
sich jetzt einstellen, je nachdem ob der Taster gedrückt ist oder nicht.

Und so gehts weiter. Eine kleine Modifikation nach der anderen, bis du 
am Ziel bist. Aber ein 'Ich schreib erst mal alles und test erst dann' 
geht bei Neulingen so gut wie immer schief.

: Bearbeitet durch User
von Tho W. (tommyprog)


Lesenswert?

Possetitjel schrieb:
> Tho Wes schrieb:
>
>> -> Frequenzen werden bis 15Hz als Blinken wargenommen (Zitat
>> aus myAVR Lehrbuch).
>
> Lehrbuch wegwerfen! (Oder aufmerksamer lesen!)
Kauf dir bitte das Buch, Schlag seite 101/198 auf, und lies die erste 
Zeile unter dem roten Rechtecksignal. -> Da steht's

> Wenn Du an einen Lautsprecher 15Hz anlegst, nimmst Du ganz
> bestimmt kein Blinken wahr!
Eine hochintelligtente Äußerung, die selbstverständlich nicht jedem 
bewusst wird.


> Wenn Du im Gegenzug an eine Leuchtdiode 1000Hz anlegst, hörst
> Du (i.d.R.) auch keinen Ton!
True.
>> Was die Tonhöhe angeht, ist das menschliche Ohr eingeschränkt.
>> Ich möchte wissen, ob man akustisch 263Hz von 440Hz unterscheiden
>> möchte.
>
> Machst Du Witze?!
Nein, sonst hätte ich es nicht hier ins Forum geschrieben.

> Mit einem Minimum an Übung kann man auch 263Hz von 270Hz unterscheiden,
> wenn die Töne nacheinander erklingen.
Okay, auch wenn man einen leichten gehörschaden hat?^^

> 263Hz und 440Hz liegen deutlich weiter auseinander als das "Ta" und
> das "Tü" beim klassischen "Tatü-Tata" der Feuerwehr.

> Es gibt aber ein ganz anderes Problem: Die Signale, die ein µC
> erzeugen kann, sind i.d.R. Rechtecksignale mit vielen Oberwellen.
> Ein Piezo hat häufig einen sehr schlechten Frequenzgang. Es kann
> also sein, dass die Töne sehr stark verfälscht wiedergegeben werden
> und dadurch schlechter unterscheidbar sind.
Genau deshalb habe ich eben gefragt, weil die Verfälschung auch im Buch 
steht^^.
> Du kannst das Intervall probeweise kleiner wählen, also z.B.
> 260Hz und 320Hz. Das ist akustisch immer noch deutlich zu
> unterscheiden.
Genau das wollte ich wissen, vielen Dank.


>> Ob ich wissen will, ob ich die Lautstärke unterscheiden will, ahbe
>> ich nie gesagt^^. Nur die Frequenz möchte ich wissen.
>
> Ohne Dir zu nahe treten zu wollen: Ich war nicht sicher, ob Dir
> der physikalische Unterschied zwischen Lautstärke und Frequenz
> überhaupt klar ist.
F= 1/ T;
L =/= 1/T;  xD

von Tho W. (tommyprog)


Lesenswert?

@Karl Heinz.

Bei deiner Berechnung hast du recht. Das steht auch so im Lehrbuch.
Mit einer wait- Funktion, habe ich bereits ein Signal über den 
Lautsprecher ausgeben können.

Was die Division angeht, so DAAAAAANKE ich dir vielmals.
Denn meines achtens nach habe ich in einen C++ Buch (C++ Lernen und 
Professionel anwenden von .Prinz) gelesen, dass wen eine variable den 
Datentyp hat, und andere nicht diesen Datentyp haben, wir es automatisch 
(.z.b wie hier in einen double) umgewandelt.
Scheinbar ist das nicht so.


Kleinere Programme habe ich bereits gemacht.
Angefangen hats mit einfachen Dauerleuchten von LED's (projekt1) bis 
über blinken lassen, dann noch mit delay, dann warens Taster, dann noch 
mit entprellen..usw..vorhin habe ich mithilfe von nen CTC- Timer2 
interrupt eine Wunderschöne unterschiedliche Frequenz bekommen... Mit 
Taster und Lautsprecher hackts aber etwas...

Mit der Nichtübernahme des Codes wollte ich dir nicht zu nahe treten.
Diesen benutze ich als geistigen Anstoß, und versuche schon, damit was 
anzufangen, auch wenn ich nur schwer von meinen eigenen wegkomm.

Die CPU frequenz habe ich schon immer eingestellt, aber ich kann nichts 
anders wählen außer den internen 1Mhz takt.
--> Da finde ich überhaupt NICHTS (auser bei den FUSES im Atmel Studio 
6), wie man einen "external Crystal" vom Typ KD0823 der mit 3.6864Mhz 
läuft (und auf der Platine mit 2 Kondensatoren verschaltet ist) in das 
Programm miteinbezieht.
Vlt. hast Du da einen Denkanstoß oder einen Link, wo es drinsteht?^^

ah, und der Grund, warum ich oben immer die "8-bit 0b- notation" mache 
ist, weil es der Arbeitgeber so übersichtlicher findet^^.


Mfg,
tommyProg

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tho Wes schrieb:

> Was die Division angeht, so DAAAAAANKE ich dir vielmals.
> Denn meines achtens nach habe ich in einen C++ Buch (C++ Lernen und
> Professionel anwenden von .Prinz) gelesen, dass wen eine variable den
> Datentyp hat, und andere nicht diesen Datentyp haben, wir es automatisch
> (.z.b wie hier in einen double) umgewandelt.
> Scheinbar ist das nicht so.

Du hast nicht verstanden, worin der Knackpunkt besteht.

Bei
1
   i = a / b;

ist der Datentyp von i völlig unerheblich dafür, wie die Division 
durchgeführt wird. Eine Division wird nicht automatisch als 
Gleitkommadivision gemacht, nur weil du dir das so einbildest. Es hängt 
von den Datentypen von a und b ab, welche Form der Division durchgeführt 
wird. Sind a und b Ganzzahltypen (also int, long, etc) dann wird da eine 
Ganzzahldivision gemacht! 8 dividiert durch 5 ergibt 1 und nicht 1 komma 
irgendwas.

Automatisch gewandelt wird nur, wenn bei einer Operation die Datentypen 
aneinander angepasst werden müssen. Aber auch da wieder: die beiden 
Datentypen der Operanden werden anhand der Operaden angepasst. Völlig 
unerheblich ist hingegen, was mit dem Ergebnis der Operation gemacht 
wird. Wenn also
1
  int a;
2
  long b;
3
4
  i = a / b;
steht, dann wird für die Division der Wert von a auf den Datentyp von b 
angepasst. D.h. der Wert aus a wird von einem int auf einen long 
umgewandelt, damit er durch den long-Wert aus b dividiert werden kann. 
Und wieder ist das eine Ganzzahldivision, da ja links und rechts vom / 
Ganzzahldatentypen stehen.
Völlig uninteressant ist hingegen, dass i möglichweise ein double ist. 
Das interessiert erst, wenn es gilt die Teiloperation
1
   i = Ergebnis aus der Division
durchzuführen. Denn dann steht auf der linken Seite der Operation = ein 
double-Datentyp während auf der rechten Seite vom = ein long Datentyp 
steht. Ergo wird dieser long (das Ergebnis aus der Division) in einen 
double umgewandelt.
Nur: Das Ergebnis der Division ist ein long, hat also keine 
Nachkommastellen. Die erscheinen auch nicht mehr magisch, nur weil 
dieses Ergebnis einem double zugewiesen wird.

von Karl H. (kbuchegg)


Lesenswert?

Tho Wes schrieb:

> Die CPU frequenz habe ich schon immer eingestellt, aber ich kann nichts
> anders wählen außer den internen 1Mhz takt.
> --> Da finde ich überhaupt NICHTS (auser bei den FUSES im Atmel Studio
> 6), wie man einen "external Crystal" vom Typ KD0823 der mit 3.6864Mhz
> läuft (und auf der Platine mit 2 Kondensatoren verschaltet ist) in das
> Programm miteinbezieht.

Die Fuses sind genau der Weg, wie man dem µC zur gefälligen 
Kentnissnahme mitteilt, dass es einen Quarz an seinen Pins gibt und das 
der gefälligst zu benutzen ist.

> ah, und der Grund, warum ich oben immer die "8-bit 0b- notation" mache
> ist, weil es der Arbeitgeber so übersichtlicher findet^^.

Da erzählt wohl ein Einäugiger einem Blinden von der wunderbaren Pracht 
der Blumen im Garten.

von Tho W. (tommyprog)


Lesenswert?

Danke dir für die ausführliche Darstellung zur Division, dann muss ich 
meinen Datentyp anpassen, was ich nach den anderen Problem noch mache.

Karl Heinz schrieb:
> Tho Wes schrieb:
>
>> Die CPU frequenz habe ich schon immer eingestellt, aber ich kann nichts
>> anders wählen außer den internen 1Mhz takt.
>> --> Da finde ich überhaupt NICHTS (auser bei den FUSES im Atmel Studio
>> 6), wie man einen "external Crystal" vom Typ KD0823 der mit 3.6864Mhz
>> läuft (und auf der Platine mit 2 Kondensatoren verschaltet ist) in das
>> Programm miteinbezieht.
>
> Die Fuses sind genau der Weg, wie man dem µC zur gefälligen
> Kentnissnahme mitteilt, dass es einen Quarz an seinen Pins gibt und das
> der gefälligst zu benutzen ist.

Yep, nur Problem ist, wenn ich bei ct_socket (oder so ähnlich) also die 
Fusedefinition bei Atmel studio durch den Programmer AVR ISP MK2 den 
Quarz auf "EXTRCOSC_OMHZ9_3MHZ_18CK_64MS" stelle, glaube ich nicht, dass 
das passend ist.
Dennoch müsste mit EXTRCOSC_OMHZ9_3MHZ_18CK_64MS definiert sein, dass es 
ein EXT (externer quarz ), mindestens 3Mhz (stimmt ja) mit nochwas dran 
(was ist nicht weiß) ist.
Was müsste ich da genau auswählen? Da kann ich viel zerstören.
mfg,
tommyProg

von spess53 (Gast)


Lesenswert?

Hi

>Dennoch müsste mit EXTRCOSC_OMHZ9_3MHZ_18CK_64MS definiert sein, dass es
>ein EXT (externer quarz ), mindestens 3Mhz (stimmt ja) mit nochwas dran
>(was ist nicht weiß) ist.

Das ist für einen externen RC-Oszillator, also eine RC-Kombination 
zwischen VCC, GND und XTAL1.

Für einen 3,.. Quarz solle "EXTMEDFXTALRES_16KCK_64MS" gehen.

MfG Spess

von Tho W. (tommyprog)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Dennoch müsste mit EXTRCOSC_OMHZ9_3MHZ_18CK_64MS definiert sein, dass es
>>ein EXT (externer quarz ), mindestens 3Mhz (stimmt ja) mit nochwas dran
>>(was ist nicht weiß) ist.
>
> Das ist für einen externen RC-Oszillator, also eine RC-Kombination
> zwischen VCC, GND und XTAL1.
>
> Für einen 3,.. Quarz solle "EXTMEDFXTALRES_16KCK_64MS" gehen.
>
> MfG Spess

Danke dir.
Wie sicher bist du dir da?

Warum soll ich nicht lieber ein "EXTMEDFXTALRES_1KCK_64MS" oder ein 
"EXTMEDFXTALRES_16KCK_0MS" benutzen.

Soviel ich weiß, ist die MS dahinter die Start-up-time.

mfg,
tommyProg

von Tho W. (tommyprog)


Lesenswert?

Tho Wes schrieb:
> spess53 schrieb:
>> Hi
>>
>>>Dennoch müsste mit EXTRCOSC_OMHZ9_3MHZ_18CK_64MS definiert sein, dass es
>>>ein EXT (externer quarz ), mindestens 3Mhz (stimmt ja) mit nochwas dran
>>>(was ist nicht weiß) ist.

Spess,

es gibt noch andere, die nur die 64 anders haben. Bist du dir zu 100% 
sicher, das EXTMEDFXTALRES_16KCK_64MS die richtige Einstellung ist?

Mfg,
tommyProg

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>es gibt noch andere, die nur die 64 anders haben.

16KCK_64MS bedeutet 16000 Takte + 64ms Start-Up-Time. Das ist die Zeit 
die der Controller nach einem Resetereignis noch wartet bis die CPU los 
läuft. Wenn nichts anderes dagegen spricht sollte man die längste 
Verzögerungszeit wählen. Da kann man auch bei langsam ansteigender 
Betriebsspannung sicher sein, das der Oszillator stabil läuft.

>Bist du dir zu 100%
>sicher, das EXTMEDFXTALRES_16KCK_64MS die richtige Einstellung ist?

Ja.

MfG Spess

von Tho W. (tommyprog)


Lesenswert?

Spess,

danke Dir.

Mfg,
TommyProg

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.