Hallo Leute, ich habe folgendes Problem:
Ich verwende den DAC eines ARDUINO DUEs, um mir jede halbe ms
abwechselnd ein Spannungswert auszugeben.
Der DA-Wandler kann aber nur jede ms (!!!) den Wert ändern, d.h. wenn
wir aus dem DA-Wandler zwei Spannungen ausgegeben haben möchten, dann
dauert das mind. 1ms.
Hier mein Code:
1
voidloop(){
2
3
analogWriteResolution(12);
4
5
analogWrite(DAC0,650);
6
delay(1);// warte 1ms
7
analogWrite(DAC1,2000);
8
delay(1);// warte 1ms
9
}
Das Funktioniert soweit einwandfrei. Setzte ich aber die delay auch nur
10µs unter der ms, schon ist der DAC dazu nicht in der Lage mehr, die
entsprechende Spannung richtig auszuben.
Das ist für einen DA-Wandler aber viiiiiiiel zu langsam. Kann man das
irgendwo einstellen?
Was ich habe is noch das Datenblatt, S.1355:
http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf
Nur leider arbeite ich grad mich in diese Materie ein, daher weiß ich
das net recht genau, wo ich das nachlesen kann.
Entschuldigt, wenn das eine dumme einfache Frage ist, jedoch häng ich
dran.
Meiner Meinung nach müsste das doch gehen, da der DAC eig. für
Audio-Anwendungen in diesem Board gedacht ist.
Jeder Dac liegt doch eig. im µs-Bereich.
Benjamin schrieb:> Meiner Meinung nach müsste das doch gehen, da der DAC eig. für> Audio-Anwendungen in diesem Board gedacht ist.
Das hängt beim SAM3 aber auch von der Masterclock ab. Wenn die zu
langsam ist, dauerts halt (DACCLK = MCLK/2). Wie die Arduino Library die
Clock einstellt, musst du also herausfinden. Die Kiste braucht 25 Takte,
um dann den DAC Ausgang zu setzen.
Für Audio mit 12 bit? Naja, schön ist anders.
Ich nehme an zu beziehst dich auf einen Arduino.
In desssen "Betriebssystem" ist die zeitliche Aflösung der
delay()-Funktion warscheinlich auf 1ms begrenzt. Wenn du
also delay(0.1) aufrufst wird das in einer Delay-Zeit von
wenigen Mikrosekunden enden - gerade das was der Aufruf und
der Rücksprung verbraucht.
Ich bin mir nicht sicher ob im Arduino-Kontext die Standard-
Aufrufe _delay_ms(....) und _delay_us(...) mmöglich sind, aber
einen Versuch ist ja es Wert .....
Ansonsten musst du lernen und dir deine eigene hochauflösende
Timer-Lösung bauen, was kein Ding der Unmöglichkeit ist.
Matthias Sch. schrieb:> Für Audio mit 12 bit? Naja, schön ist anders.
Was würdest du denn sagen wenn man dir sagt dass in *.mp3
Dateien die Audio Daten oft auf noch weniger als 12 Bit
"komprimiert" werden?
Mitlesa schrieb:> Ich bin mir nicht sicher ob im i4004-Kontext die Standard-> Aufrufe _delay_ms(....) und _delay_us(...) mmöglich sind, aber> einen Versuch ist ja es Wert .....
Der Versuch war es wert. Da lag der Fehler.
Wenn ich delayµs aufrufe, dann klappts ! Danke !
@ Benjamin (Gast)
>Wobei wenn ich wiederum beide DACs verwende, dann ist der zu langsam>bzw. schafft es nicht.
Dann machst du was falsch. 1 kHz ist ein Witz für einen DAC.
Wie sieht den Programm JETZT aus?
Das Problem liegt wahrscheinlich in der Funktion analogWrite();
Mitlesa schrieb:> Matthias Sch. schrieb:>> Für Audio mit 12 bit? Naja, schön ist anders.>> Was würdest du denn sagen wenn man dir sagt dass in *.mp3> Dateien die Audio Daten oft auf noch weniger als 12 Bit> "komprimiert" werden?
Dann sage ich immer noch - schön ist anders. Verwechsle auch bitte nicht
die komprimierten Daten mit dem, was am DAC wieder auftaucht.
Falk Brunner schrieb:> Dann machst du was falsch. 1 kHz ist ein Witz für einen DAC.> Wie sieht den Programm JETZT aus?>> Das Problem liegt wahrscheinlich in der Funktion analogWrite();
Mein Programm sieht wie folgt aus:
1
analogWriteResolution(12);
2
3
analogWrite(DAC0,100);
4
5
delayMicroseconds(500);
6
7
analogWrite(DAC0,0);
8
9
delayMicroseconds(500);
500 µs ist das absolute minimum was geht, dannach kann er das ganze
nicht mehr in der angegebenen Zeit schaffen, d.h. wenn ich 250µs An/Aus
eingebe, dann ist er 230µs an und 270µs aus.
Im Übrigen, wenn ich beide DAC-Ausgänge verwende, dann ist nach 1ms
schon schluss. Mein Code sieht dann wie folgt aus:
1
analogWriteResolution(12);
2
3
analogWrite(DAC0,100);
4
analogWrite(DAC1,100);
5
6
delay(1);
7
8
analogWrite(DAC0,0);
9
analogWrite(DAC1,0);
10
11
delay(1);// 1 steht für 1ms
1ms bekommt der sauber hin.
Auch nur eine µs drunter führt schon zu Problemen.
auch wenn ich die Funktion delayMicroseconds verwende, dann können die
Zeiten nicht mehr exakt eingehalten werden.
Genau deswegen wende ich mich an euch: Nämlich ich denke auch, dass das
ein Witz ist mit 1kHz.....
aus der Gerüchteküche:
Der Vorgang ist viel fixer wenn du auf analogWrite() verzichtest und den
DAC direkt manipulierst.
Und noch feiner, wenn DMA zum Einsatz kommt.
*alles (von mir) ungetestet*
Benjamin schrieb:> Genau deswegen wende ich mich an euch: Nämlich ich denke auch, dass das> ein Witz ist mit 1kHz.....
Du hast dir aber schon mal MCLK und die davon abgeleitete DAC Clock
angesehen? Das bestimmt die obere Grenze dessen, was der DAC verdauen
kann, nämlich DACClock/25.
Der Nachteil bei der Arduino Lib ist oft der, das man nicht weiss, was
die Jungs bei der Initialisierung anstellen. Schau dir die also mal an.
Das Problem ist aber, das ich leider nur die Arduino IDE verwende, bin
nicht der fitteste darin, irgendwo etwas zu manipulieren.
Besteht keine Möglichkeit das irgendwie über die Arduino IDE zu ändern
oder ähnliches?
Benjamin schrieb:> Besteht keine Möglichkeit das irgendwie über die Arduino IDE zu ändern> oder ähnliches?
Natürlich. Hinter "analogWrite" steckt ja auch nichts anderes als C++
Code in irgendeiner Datei. Die kann man suchen und sich mal ansehen.
Ich schätze aber mal, da wirst du kein Glück haben. Denn analogWrite
muss aus Komfortgründen eine ganze Menge mehr machen, was zwar für
Lieschen Müller kein Problem darstellt (ganz im Gegenteil), wenn man
aber die Hardware ausreizen will, dann ist das kontraproduktiv.
Witers schätze ich mal, du wirst nicht umhin kommen zu lernen, wie man
den DAC direkt, also ohne Mithilfe der Arduino-Entwickler und deren
analogXXX Funktionen programmiert.
Und ich hoffe auch, du hast gelernt, dass diese Rederei von wegen "Nimm
einen Arduino, da braucht man nichts können" ganz einfach so nicht
stimmt. Solange man keine speziellen Ansprüche hat, mag das gehen. Aber
wehe, wenn man dann mal etwas braucht, was nicht in das vorgefertigte
und von anderen vorgedachte Schema passt. Dann ist man aufgeschmissen.
Benjamin schrieb:> Besteht keine Möglichkeit das irgendwie über die Arduino IDE zu ändern> oder ähnliches?
Ich kann nicht glauben, daß es zu der Arduino-Lib kein Manual geben
soll, wo alle Parameter und Limits erläutert werden.
Ansonsten kann man die Lib auch einfach nicht benutzen und ins
Datenblatt/Manual des MC schauen, um die Register direkt zu setzen.
Ganz ohne Lesen von Manuals wird man aber nicht weit kommen.
Nee..
Arduino ist auf dem Auge recht Blind.
Es gibt von Arduino eine Audio/DAC Lib. (die könnte man sich mal
ansehen)
Und andere haben auch schnelle Ausgaben bis 44100 Werten pro Sekunde
hin bekommen. Mit Assembleranteilen.
Natürlich geht das alles mit/in der Arduino IDE, wird aber nicht direkt
durch vorgefertigte Dinge unterstützt.
Aber wie gesagt, ist nicht meine Baustelle und auch nur aus der
Erinnerung geholt.
@Benjamin (Gast)
>Mein Programm sieht wie folgt aus:
GANZ SICHER NICHT!
Lass den Mist mit dem hinschreiben von Fetzen aus dem Gedächtnis! Poste
VOLLSTÄNDIGEN, ORIGINALEN Code als ANHANG! Siehe Netiquette!
>500 µs ist das absolute minimum was geht, dannach kann er das ganze>nicht mehr in der angegebenen Zeit schaffen, d.h. wenn ich 250µs An/Aus>eingebe, dann ist er 230µs an und 270µs aus.>auch wenn ich die Funktion delayMicroseconds verwende, dann können die>Zeiten nicht mehr exakt eingehalten werden.
Dafür sind die Funktion so auch nicht in der Lage. Ein WIRKLICH sauberes
Timing erreicht man nur mit einem Timer-Interrupt. Das liegt aber
jenseits der Arduinowelt.
Bei mir finden sich in
C:\Programme\Arduino\hardware\arduino\sam\system\libsam
Die Ordner include und source.
Dort befindet sich der DAC spezifische Krams.
Das kann man sich auch mal ansehen.
Vielleicht ist damit was machbar.
Falk Brunner schrieb:> Ein WIRKLICH sauberes> Timing erreicht man nur mit einem Timer-Interrupt.
In dem Falle wüde ich eher Hardware-getriggertes DMA für den DAC
verwenden.
Das verwendet einen Timer für den Trigger aber keinen Timer-Interrupt.
Das hat dann noch weniger Jitter, aber auch mehr Möglichkeiten für den
Programmierer sich selbst ins Knie zu schiessen.
@Jim Meba (turboj)
>In dem Falle wüde ich eher Hardware-getriggertes DMA für den DAC>verwenden.>Das verwendet einen Timer für den Trigger aber keinen Timer-Interrupt.
Ja, das ist noch besser, aber . . .
>Das hat dann noch weniger Jitter, aber auch mehr Möglichkeiten für den>Programmierer sich selbst ins Knie zu schiessen.
Eben noch weiter weg von Arduino.
Falk Brunner schrieb:> @Jim Meba (turboj)>>>In dem Falle wüde ich eher Hardware-getriggertes DMA für den DAC>>verwenden.>>Das verwendet einen Timer für den Trigger aber keinen Timer-Interrupt.>> Ja, das ist noch besser, aber . . .>>>Das hat dann noch weniger Jitter, aber auch mehr Möglichkeiten für den>>Programmierer sich selbst ins Knie zu schiessen.>> Eben noch weiter weg von Arduino.
Liebe Leute, vielen Dank für eure Antwortn, es hat super geklappt, hab
das über einen Timer realisiert...
@ Benjamin (Gast)
>Liebe Leute, vielen Dank für eure Antwortn, es hat super geklappt, hab>das über einen Timer realisiert...
Na dann poste mal deinen Quelltext.
Falk Brunner schrieb:> Na dann poste mal deinen Quelltext.
Mehr als ein Blockschaltbild ist nicht drin, da ich das in Simulink über
ne S-Function realisiert habe, wenn einer Interesse hat, dann gerne ....