PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sound-Probleme mit dem Demoprogramm in C + kurze Fragen



Manni2k
12.04.2010, 19:29
Hallo,

1)

das RN-Control Demoprogramm in C (http://www.rn-wissen.de/index.php/RN-Control_Demoprogramm_in_C) sorgt bei mir dafür, dass sich der Sound schrecklich anhört, in folgendem Sinne:
Er ist sehr lang und grell und unschön - sicher nicht gewollt - ich konnte ihn ja mit der Startmelodie von dem Bascom-Demoprogramm vergleichen, was anfangs dort drauf war.
Ich habe mir mal die sound()-Funktion kurz angeschaut und festgestellt, dass der Aufruf "sound(6, 270);" (ein Teil der Melodie) insgesamt etwa 4 Sekunden wartet durch die beiden Aufrufe von "_delay_ms(hoehe);" - das heißt die Startmelodie dauert durch 7x Aufrufe von sound() etwa 28 Sekunden ?! Ist das gewollt ?! Irgendwas muss da doch faul sein? Ich kann den Sound gerne mal aufnehmen und rein stellen ;)

2)

Das RN-Control Demoprogramm in C reagiert nicht auf den Reset-Taster - muss man den selbst im Code ansprechen und darauf reagieren oder ist der direkt am Mikrocontroller angeschlossen, sodass dieser sich unabhängig vom Programm-Code IMMER resettet? Letzteres kann eigentlich nicht sein, denn das LED-Lauflicht wird durch das Drücken des Reset-tasters nicht unterbrochen...

3)

Noch eine kurze Frage zum RN-Control:
Der An/Aus-Knopf fehlt komplett, oder? Hat das einen speziellen Grund? Ich meine, ist ja schon blöd, wenn Batterien dran hängen.

Vielen Dank & Viele Grüße,
Sören

Manni2k
12.04.2010, 19:52
Zu 1):
Ich habe mal "_delay_us" statt "_delay_ms" genommen - und schon kommen da jedenfalls brauchbare, nicht mehr klirrende, wackelige Töne raus, sondern hohe Piepser - nur ist die Startmelodie immernoch unharmonisch und nicht "originale" - und die Töne werden, je nach Parameter "hoehe" unterschiedlich lange abgespielt.

Max Web
13.04.2010, 19:33
Hallo,

Zu 1): Das würde mich auch sehr interessieren, ich selbst habe es noch nicht hinbekommen. Auch mit der im Internet kursierenden delay_x nicht umgehbar.

Zu 2): Der Reset-Taster zieht den Reset-Pin am Mega32 auf Masse, dadurch startet der Mega32 neu.

Zu 3): Einen solchen Knopf hat das Board nicht. Man kann aber auch einfach einen Schalter anschließen.

Manni2k
13.04.2010, 19:47
Danke erstmal für deinen Beitrag.
Zu 2): Das dachte ich mir auch, hat auch wunderbar funktioniert bei dem BASCOM-Demoprogramm was anfangs drauf war, allerdings reagiert das C-Demoprogramm gar nicht mehr auf den Reset-Knopf - wie schaut es bei dir/euch aus?

Hubert.G
13.04.2010, 20:54
Das mit dem Demo wurde hier schon einige mal behandelt.
Es hängt damit zusammen das dem _delay_ms keine Variable übergeben werden darf, nur Konstante sind zugelassen, siehe avr-libc-user-manual.
Umgehungsmöglichkeit mit while.

Manni2k
14.04.2010, 00:57
Das mit dem Demo wurde hier schon einige mal behandelt.
Das ist schön. Aber warum integriert man die Diskussion nicht dahin, wo sie hingehört: Und zwar in die Diskussions-Seite über das C-Demoprogramms? Oder warum wird das Demoprogramm nicht mal angepasst, wenn Fehler drin sind? Ich würde es ja selber auch machen, wenn ich denn eine Lösung parat hätte bzw. das Problem verstehen würde, wo wir gleich beim nächsten Punkt sind:


Es hängt damit zusammen das dem _delay_ms keine Variable übergeben werden darf, nur Konstante sind zugelassen, siehe avr-libc-user-manual.
Ich habe mal in der Doku nachgeschaut, dort steht zu "_delay_ms" folgendes:


Perform a delay of __ms milliseconds, using _delay_loop_2().

The macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).

The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

Wo steht, dass nur Konstanten erlaubt sind?
Leider scheint es auch nicht daran zu liegen: Ich habe mal eine Konstante eingesetzt, und das Problem besteht immer noch. Außerdem nochmal: Wenn delay_ms wirklich stimmen sollte und das Grundgerüst auch, so würde die Startmelodie über 20 Sekunden dauern (s.o.) - das wird so nicht richtig sein! Und nochmal: Nach einem Wechsel auf "delay_us" (Also WENIGER warten -> Mikro- statt Millisekunde) kommen bei mir jedenfalls brauchbarere Töne raus.

Kann wer, der diesen Piepser brauchbar in C ansprechen kann, nicht mal seinen Code veröffentlichen?

Vielen Dank nochmal für jegliche Mühe!

Viele Grüße,
Sören

Hubert.G
14.04.2010, 09:49
Das steht in der GCC Referenz Lib

In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. If these requirements are not met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise do not use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application.
Wie hast du denn die Fuses deines Mega32 eingestellt?

Manni2k
14.04.2010, 17:00
Ah okay, danke für das Zitat.

Die Fuses- und Lockbits habe ich unverändert gelassen, die waren bei Auslieferung ja schon richtig konfiguriert, nicht?
Die Frequenz passt auch, das Lauflicht läuft genauso, wie es soll.

Manni2k
14.04.2010, 19:03
Ich denke, dass ich es jetzt hinbekommen habe - leider fehlt mir die Original-Bascom-Startmelodie, aber diese hier klingt jetzt jedenfalls auch schön.

Verwendet habe ich die Basis-Delay-Funktion _delay_loop_2(i), welche bei 16MHz und i=1 etwa (+/- Setup-Delay) 0,25 µs wartet.

Ich ersetze in der sound()-Funktion lediglich jeweils _delay_ms(hoehe); durch _delay_loop_2(150*hoehe); - was dann in seiner Gesamtheit folgendermaßen aussieht:



void sound(uint8_t hoehe, uint16_t laenge)
{
for(uint16_t i=0; i<laenge*15; i=i+(2*hoehe))
{
setportdon(7);
_delay_loop_2(150*hoehe);
setportdoff(7);
_delay_loop_2(150*hoehe);
}
}


Man kann sich mit Hilfe von void _delay_loop_2 (uint16_t __count) auch eine zweite waitms-Funktion bauen, die folgendermaßen aussieht (erfolgreich getestet bei z.B. 3s-Wartezeit):



void waitms2(uint16_t ms)
{
for(; ms>16; ms-=16)
{
_delay_loop_2(64000); // 64000 = 16 * 4000
}

_delay_loop_2(4000*ms);
}


Kann mir jemand bitte bestätigen, dass es wie hier beschrieben dann funktioniert?

Den Sound kann man mit der Konstante 150 noch ein wenig variieren.

Ich würde dann auch gerne das C-Demoprogramm modifizieren wollen, wohl wissend, dass es insgesamt vlt. sinnvoller wäre, Timer zu verwenden - aber das würde für das Demoprogramm wohl zu weit gehen. Ich denke, dass diese kleine Änderung (im Prinzip nur die beiden Zeilen) okay sind - oder?

Viele Grüße,
Sören

Manni2k
15.04.2010, 04:00
2) auch gelöst: Wenn der ISP-Programmer angesteckt ist, funktioniert der Reset-Button nicht - nimmt man ihn raus, reagiert das Programm wieder auf den Reset. Mir auf die Schnelle schleierhaft, aber egal ;)

Manni2k
17.04.2010, 16:48
Nochmal: Könnte mir jemand bitte bestätigen, dass die Änderung im C-Demoprogramm

Ich ersetze in der sound()-Funktion lediglich jeweils _delay_ms(hoehe); durch _delay_loop_2(150*hoehe);
dazu führt, dass der Sound jetzt ordentlich klingt?

Dann könnte ich das C-Demoprogramm dementsprechend modifizieren.

Ihr habt doch alle ein RN-Control, bitte testet das doch einer kurz, damit die Änderung jedenfalls halbwegs verifiziert ist ;)

Danke!

Hubert.G
17.04.2010, 21:01
Wie kommst du auf 150*hoehe ?
Ich muss 420 nehmen um einen einigermassen guten Ton zu erreichen.
Das Original kenne ich allerdings auch nicht.
Bin aber auch nicht sehr musikalisch.
Die 420 sollten rechnerisch bei 16MHz einen Startton von etwa 800Hz ergeben.

Manni2k
17.04.2010, 22:13
Hm, komisch.
Ich bin mittlerweile zu 128 als Konstante übergegangen und verwende folgenden Code:


void sound(uint8_t hoehe, uint16_t laenge)
{
for(uint16_t i=0; i<laenge*15; i=i+(2*hoehe))
{
setportdon(7);
_delay_loop_2(hoehe<<7); // wait for 0,032*hoehe ms with F_CPU of 16 MHz
setportdoff(7);
_delay_loop_2(hoehe<<7); // wait for 0,032*hoehe ms with F_CPU of 16 MHz
}
}

Der Ton sound(6, 270); dauert bei mir etwa 0,13ms (sowohl rechnerisch als auch experimentell bestimmt!). verwendest du auch die neueste avr-libc? nicht dass wir mit unterschiedlichen "_delay_loop_2"-Implementierungen arbeiten ;)

Ich habe als Anhang mal die Startmelodie beigelegt, die sich bei mir mit obigem Code ergibt - bei dir hört es sich nicht so an? Mit 420 sind bei mir die Töne viel zu langgezogen, da wird die Startmelodie ja noch viel länger ;)

Die Startmelodie der Bascom-Version ist grundlegend anders (vor allem viel kürzer) - warum auch immer (da hatte wohl wer Spass am Komponieren).

Hubert.G
17.04.2010, 22:33
Das was du da geschickt hast ist das was sich bei mir mit deinem Wert ergibt.
Das ist allerdings nur ein kurzes zwitschern und keine Melodie.
Das gleiche habe ich auch mit dem anderen delay und einer for-Schleife zusammen gebracht. Da es aber so kurz war, dachte ich es ist da noch ein Wurm drinnen.
Aber die BASCOM Melodie kenne ich ja nicht.

Manni2k
17.04.2010, 22:46
Das soll ja auch nur ein kleines "Zwitschern" beim Start sein, aber das kann man doch trotzdem als Melodie bezeichnen?
Die BASCOM-Version ist noch viel kürzer und hat glaube ich nur 2 Töne (A-B-A) oder so.

Vlt. geht es noch anders, aber ich denke, dass es so die eleganteste Lösung ist. Zumal man nicht in der anderen waitms() Funktion rumfuscht und damit das Lauflicht kaputt macht.

Soll ich die C-Demoversion dann anpassen, oder gibt es an dieser Version noch was auszusetzen?

Hubert.G
18.04.2010, 09:40
Wenn die BASCOM Version so ähnlich ist, dann passt es meiner Ansicht nach schon.

Manni2k
18.04.2010, 16:00
Gut, Diskussions-Seite und Hauptartikel sind angepasst.
Damit dürfte dieses Thema dann beendet sein.
Danke dir für deine Hilfe ;)