Forum: Mikrocontroller und Digitale Elektronik DAC 8-Bit Atmega8 sehr langsam


von Dennis B. (mikrohenry)


Lesenswert?

Hallo!
Bin gerade beim Bau eines Sinusgenerators mit Hilfe eines Atmega8 und 
R2R-Widerstandsnetzwerk (8Bit). Soweit funktioniert das auch recht gut, 
allerdings ist die maximale Sinusfrequenz bloß bei etwa 1kHz und ich 
würde ca. 20 kHz benötigen. Ich vermute durch den Befehl "Incr" wird die 
ganze Sache so langsam? Wie könnte ich die Tabelle noch hochzählen?

Danke für eure Antworten!!


Ich verwende folgende Programmierung in Bascom:
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

$regfile = "m8def.dat"
$crystal = 16000000

Config Portd = Output

Dim Nummer As Byte

Do
Portd = Lookup(nummer , Sine_table)
Incr Nummer
Loop

End
Return

Sine_table:
Data 128 , 131 , 134 , 137 , 140 , 143 , 146 , 149
Data 152 , 155 , 158 , 162 , 165 , 167 , 170 , 173
Data 176 , 179 , 182 , 185 , 188 , 190 , 193 , 196
Data 198 , 201 , 203 , 206 , 208 , 211 , 213 , 215
Data 218 , 220 , 222 , 224 , 226 , 228 , 230 , 232
Data 234 , 235 , 237 , 238 , 240 , 241 , 243 , 244
Data 245 , 246 , 248 , 249 , 250 , 250 , 251 , 252
Data 253 , 253 , 254 , 254 , 254 , 255 , 255 , 255
Data 255 , 255 , 255 , 255 , 254 , 254 , 254 , 253
Data 253 , 252 , 251 , 250 , 250 , 249 , 248 , 246
Data 245 , 244 , 243 , 241 , 240 , 238 , 237 , 235
Data 234 , 232 , 230 , 228 , 226 , 224 , 222 , 220
Data 218 , 215 , 213 , 211 , 208 , 206 , 203 , 201
Data 198 , 196 , 193 , 190 , 188 , 185 , 182 , 179
Data 176 , 173 , 170 , 167 , 165 , 162 , 158 , 155
Data 152 , 149 , 146 , 143 , 140 , 137 , 134 , 131
Data 128 , 124 , 121 , 118 , 115 , 112 , 109 , 106
Data 103 , 100 , 97 , 93 , 90 , 88 , 85 , 82
Data 79 , 76 , 73 , 70 , 67 , 65 , 62 , 59
Data 57 , 54 , 52 , 49 , 47 , 44 , 42 , 40
Data 37 , 35 , 33 , 31 , 29 , 27 , 25 , 23
Data 21 , 20 , 18 , 17 , 15 , 14 , 12 , 11
Data 10 , 9 , 7 , 6 , 5 , 5 , 4 , 3
Data 2 , 2 , 1 , 1 , 1 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 1 , 1 , 1 , 2
Data 2 , 3 , 4 , 5 , 5 , 6 , 7 , 9
Data 10 , 11 , 12 , 14 , 15 , 17 , 18 , 20
Data 21 , 23 , 25 , 27 , 29 , 31 , 33 , 35
Data 37 , 40 , 42 , 44 , 47 , 49 , 52 , 54
Data 57 , 59 , 62 , 65 , 67 , 70 , 73 , 76
Data 79 , 82 , 85 , 88 , 90 , 93 , 97 , 100
Data 103 , 106 , 109 , 112 , 115 , 118 , 121 , 124

von Bernie (Gast)


Lesenswert?

Ich bevorzuge ja Assembler, aber "Incr" sollte selbst in
Bascom nicht sehr viele Prozessortakte benötigen.

Allerdings nützt "$crystal = 16000000" nicht viel,
wenn der µC nicht mit 16 MHz getaktet wird.

Wie betreibst du denn den Mega8?

von Dennis B. (mikrohenry)


Lesenswert?

Danke für Deine Antwort!

Die 16Mhz passen schon, ich habe einen externen 16Mhz Quarz an den 
Atmega8 angeschlossen.

Gruß Dennis

von Floh (Gast)


Lesenswert?

Xyz Zyx schrieb:
> Die 16Mhz passen schon, ich habe einen externen 16Mhz Quarz an den
> Atmega8 angeschlossen.

Auch die Fuses passend gesetzt?

von Dennis B. (mikrohenry)


Angehängte Dateien:

Lesenswert?

Jop, die Fuses müssten auch passen (siehe Bild), oder?

Gruß Dennis

von Bernie (Gast)


Lesenswert?

20 kHz sind aber etwas viel verlangt:

16.000.000 / 20.000 = 800

man hat also 800 Prozessortakte frei um 256
DA-Ausgaben zu machen. Das sind 3,125 Takte für
jeden DA-Wert. DAS REICHT BESTIMMT NICHT!

Allerdings sollten 4...5 kHz schon drin sein...

von Uwe (de0508)


Angehängte Dateien:

Lesenswert?

Hallo,

teste bitte mal diese HEX-Datei deines Programms auf deiner Hardware.

AVR atMega8
Frequenz 16 MHz
DAC Ausgabe an PortD

Was zeigt der Frequenzzähler an ?

_

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Bernie schrieb:
> Ich bevorzuge ja Assembler, aber "Incr" sollte selbst in
> Bascom nicht sehr viele Prozessortakte benötigen.
>
> Allerdings nützt "$crystal = 16000000" nicht viel,
> wenn der µC nicht mit 16 MHz getaktet wird.
>
> Wie betreibst du denn den Mega8?

Auch bei tatsächlichen 16 MHz wirds in Assembler knapp, wenn man das in 
einer Schleife erledigen will. Gehen wir davon aus, die Tabelle liegt im 
SRAM (wäre am schnellsten), dann brauchst du immer noch 5 Takte pro 
Wert: Laden mit LD, inkrementieren mit INC, ausgeben mit OUT und 
springen mit RJMP (2 Takte). Frequenz:
1
16 000 000 / 256 / 5 = 12 500 Hz

Durch einen Trick kannst du auf die RJMP verzichten, wenn du das 
Programm linear schreibst und nur zu Zeiten springst, in denen sich der 
auszugebende Wert ein paar Takte lang nicht ändert (da sind ein paar 
aufeinander folgende Stellen mit 0 in der Tabelle). Dann sind es nur 
noch 3 Takte je Wert, und die Rechnung ändert sich wie folgt:
1
16 000 000 / 256 / 3 = 20 833 Hz

Noch schneller gehts, wenn man keine Tabelle verwendet, sondern die 
Werte per LDI direkt ins Programm schreibt:
1
16 000 000 / 256 / 2 = 31 250 Hz

Wenn man unbedingt den ATmega8 nehmen will, der ab 16 MHz schon am Ende 
ist, dann bleibt ja noch, die Tabelle nicht gar so fein zu unterteilen, 
also zum Beispiel nur 128 Werten zu verwenden.

Oder man weicht auf geeignetere Hardware aus. :-)

von Jobst M. (jobstens-de)


Lesenswert?

Wenn man es drauf anlegt, kommt man in ASM mit 2 Takten/Sample aus.
- Da war jemand anders schneller ...

Wie sieht denn das aus, was der Compiler erzeugt?


Gruß

Jobst

von Bernie (Gast)


Lesenswert?

Selbst in Assembler wirds eng:

Es klappt auch nur, wenn die Tabelle genau an einer
Adresse anfängt, bei der XL = 0x00 ist.

Der µC ist dann auch nicht in der Lage, irgend etwas Anderes
(Reaktion auf Tasten, ...) zu bearbeiten.

da_loop:
    inc XL              1
    ld Tmp0, X          2
    out PortD, Tmp0     1
    rjmp   da_loop      2
                      =====
Benötigte Takte:        6

Das ergibt die erforderliche Taktfreqenz:
6  256  20.000 = 30.720.000 MHz

von Floh (Gast)


Lesenswert?

Wenns nicht schnell genug ist, muss man entweder das Increment pro 
Durchlauf vergrößern oder die Tabelle kleiner machen, so dass insgesamt 
von mir aus nur 100 Werte pro Sinusschwingung am DA landen.

von Dennis B. (mikrohenry)


Lesenswert?

@Uwe S.
Habe die HEX-Datei getestet. Leider erreiche ich so nur etwa 700Hz.
Trotzdem Danke!

@Markus Weber
Habe auch schon eine kleinere Tabelle benutzt, jedoch schafft er dann 
auch nicht höhere Frequenzen!?

Wie funktioniert denn der Generator hier? :
http://www.dl8nci.de/DDS-001.html

Gruß

von Bernie (Gast)


Lesenswert?

@ Markus Weber

Warst ja etwas schneller.
Aber "ld X" braucht bei mir zwei Takte! ;-)

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Bernie schrieb:
> @ Markus Weber
>
> Warst ja etwas schneller.
> Aber "ld X" braucht bei mir zwei Takte! ;-)

Hmmm, wir hatten die gleichen Ideen. :-)

Bei "LD" steht in meinem Datenblatt, dass er nur einen Takt braucht 
(wenn nicht Inkrement oder Dekrement dabei ist).
Dokument "Instruction Set", Seite 89. Kann aber sein, dass das ein 
Fehler ist.

von Uwe (de0508)


Lesenswert?

Xyz Zyx schrieb:
> Habe die HEX-Datei getestet. Leider erreiche ich so nur etwa 700Hz.
> Trotzdem Danke!

ja ich habe auch mal schnelle das Programm auf einen atMega32 mit 
14,7456MHz geladen und mit einem 100MHz Oszilloskop die Frequenz 
gemessen: 711Hz.

Die Idee, die Daten aus dem SRAM zu holen habe ich mit LunaAVR umgesetzt 
und da liegt die Frequenz des Bit7 bei 3,03KHz @14,7456MHz Takt.

.

von Sam .. (sam1994)


Lesenswert?

Hat noch niemand hier was von DDS gehört? Darauf sollte man eigentlich 
aber schon so drauf kommen.

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

Noch'n Hex-File.

2-Takter ... :-D

Sollte bei 16MHz 31.25kHz produzieren ...


Gruß

Jobst

von Jobst M. (jobstens-de)


Lesenswert?

Sam .. schrieb:
> Hat noch niemand hier was von DDS gehört?

Und - das behebt nun sein Problem - oder wie?


Gruß

Jobst

von Ziegenpeter (Gast)


Lesenswert?

Jobst M. schrieb:
> 2-Takter ... :-D

Wollte auch gerade meinen 2-Takter posten.
Ich schätze, du hast es ähnlich gelöst:
1
loop:
2
ldi r16, 128
3
out PortD, r16
4
ldi r16, 131
5
out PortD, r16
6
ldi r16, 134
7
out PortD, r16
8
ldi r16, 137
9
out PortD, r16
10
ldi r16, 140
11
out PortD, r16
12
ldi r16, 143
13
out PortD, r16
14
.
15
.
16
.
17
ldi r16, 118
18
out PortD, r16
19
ldi r16, 121
20
out PortD, r16
21
ldi r16, 124
22
out PortD, r16
23
rjmp loop

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

Ziegenpeter schrieb:
> Ich schätze, du hast es ähnlich gelöst

Jain. Ich springe bei den 0-en. Du hast eine Stufe während des RJMPs ...

Gerade stelle ich noch einen Fehler fest ... Grmph ...

Nun aber - V3 :-D


Gruß

Jobst

von Axel S. (a-za-z0-9)


Lesenswert?

Der Trick besteht darin, je nach gewünschter Frequenz Tabellenwerte 
entweder zu überspringen oder aber mehrfach auszugeben. Stichwort 
Phasenakkumulator.

Jesper hat das vor 12 Jahren schon vorgemacht:

http://www.myplace.nu/avr/minidds/index.htm


XL

von Helmut L. (helmi1)


Lesenswert?

Bernie schrieb:
> 20 kHz sind aber etwas viel verlangt:
>
> 16.000.000 / 20.000 = 800
>
> man hat also 800 Prozessortakte frei um 256
> DA-Ausgaben zu machen. Das sind 3,125 Takte für
> jeden DA-Wert. DAS REICHT BESTIMMT NICHT!

Warum 256 Werte für eine Periode ausgeben?
Da reichen wesentlich weniger Werte. Stichwort DDS.

Jobst M. schrieb:
> Sam .. schrieb:
>> Hat noch niemand hier was von DDS gehört?
>
> Und - das behebt nun sein Problem - oder wie?

Ja. Bei höhren Frequenzen kann man den Phasenschritt wesentlich grösser 
machen. Also keine 256 Werte pro Periode. Das Filter am Ausgang 
rekonstruiert daraus wieder einen Sinus. Und damit kommt man dann auch 
höher in der Frequenz.

Axel Schwenke schrieb:
> Jesper hat das vor 12 Jahren schon vorgemacht:

@Axel

Es dauert halt bis sich so was rumspricht :=)

von Jobst M. (jobstens-de)


Lesenswert?

Helmut Lenzen schrieb:
> Jobst M. schrieb:
>> Sam .. schrieb:
>>> Hat noch niemand hier was von DDS gehört?
>>
>> Und - das behebt nun sein Problem - oder wie?
>
> Ja.

Nein

> Bei höhren Frequenzen kann man den Phasenschritt wesentlich grösser
> machen. Also keine 256 Werte pro Periode. Das Filter am Ausgang
> rekonstruiert daraus wieder einen Sinus. Und damit kommt man dann auch
> höher in der Frequenz.

Mir ist durchaus bewusst, wie ein DDS-Generator arbeitet. Trotzdem 
behebt das das Problem nicht. Nochmal zum mitschreiben: Der TO benötigt 
in seinem Programm offenbar 90 Takte, um einen Sample auszugeben.
Die Frage ist, warum ist das so?

'Nimm DDS' beantwortet diese Frage nicht.


Gruß

Jobst

von Axel S. (a-za-z0-9)


Lesenswert?

Jobst M. schrieb:
> behebt das das Problem nicht. Nochmal zum mitschreiben: Der TO benötigt
> in seinem Programm offenbar 90 Takte, um einen Sample auszugeben.
> Die Frage ist, warum ist das so?

Er hat sein Programm in BASIC geschrieben. Da muß ich keine weiteren 
Details wissen. In Ermangelung einer Beschreibung, welches Problem er 
lösen wollte, können wir noch nicht mal sagen ob sein Lösungsansatz 
überhaupt taugt. Aber BASCOM erscheint mir schon mal als schlechte Wahl.


XL

von Dennis B. (mikrohenry)


Lesenswert?

Hallo!
Danke für eure Antworten!
Habe nun noch etliche Versuche mit niedrigerer Auflösung gemacht (7Bit, 
6Bit, 5Bit...) und trotzdem noch gute Signalkurven gemessen. Nun schafft 
er etwa 15kHz ;) das ist für die jetzigen Bedürfnisse ausreichend.


Danke für die Bemühungen


Gruß Dennis

von Tim (Gast)


Lesenswert?

Geht scheinbar auch 1Hz bis 200 kHz problemlos, vielleicht kannst du die 
Technik ja in dein Basic portieren:


http://avr.myluna.de/doku.php?id=de:ddsgen.luna

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.