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
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.
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.
>> } 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
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
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ß
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(....ZeitfüreineHalbwellebei440Hz...);
29
}
30
31
elseif(Modus==TON_B){
32
PORTB^=Lautsprecher_an;
33
_delay_ms(....ZeitfüreineHalbwellebei263Hz...);
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.
@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
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
>#defineKEIN_TON0
3
>#defineTON_A1
4
>#defineTON_B2
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(....ZeitfüreineHalbwellebei440Hz...);
30
>}
31
>
32
>elseif(Modus==TON_B){
33
>PORTB^=Lautsprecher_an;
34
>_delay_ms(....ZeitfüreineHalbwellebei263Hz...);
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
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. :)
@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
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.
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
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.
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
intmain()
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
doubleendwert=(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
intmain()
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.
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
@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
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
inta;
2
longb;
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=ErgebnisausderDivision
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.
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.
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
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
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
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
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