Forum: Mikrocontroller und Digitale Elektronik Suche Xmega Sinus Quellcode


von Daniel M. (marcus123)


Lesenswert?

Hallo liebes Forum,
ich suche einen Quellcode für einen Xmega der einen Sinus erzeugt.
Am besten wäre ein Quellcode , in dem die Frequenz eingestellt werden 
kann. Also nicht von aussen über ein Poti oder so.

Hoffe das Ihr mir weiterhelfen könnt.

:
von Purzel H. (hacky)


Lesenswert?

>Hoffe das Ihr mir weiterhelfen könnt.

Nein, leider nicht. Das ist zu trivial. Wo genau liegt das Problem ?

von Daniel M. (marcus123)


Lesenswert?

Das Problem ist, das ich bisher nur codes gefunden habe, die auf einem 
Wavegenerator basieren.
zb: 
http://www.instructables.com/id/Easy-Atmel-Xmega-Sine-Wave-Generator/?ALLSTEPS#step8

nur hierbei wird die Frequenz über ein Poti eingestellt.

Deswegen Suche ich einen Quellcode in dem über eine Variable die 
Frequenz eingestellt werden kann. Denn je nachdem was für Daten anliegen 
benötige ich eine andere Frequenz. genauer zwei frequenzen. 18 und 
22khz. Des Weiteren wäre es von Vorteil wenn sich Wiederholungen 
einstellen liessen.

von Helmut S. (helmuts)


Lesenswert?

Nimm halt den Code von hier. Der dürfte mit wenigen Änderungen passen.
http://www.mikrocontroller.net/articles/Digitaler_Funktionsgenerator

von Daniel M. (marcus123)


Lesenswert?

Helmut S. schrieb:
> Nimm halt den Code von hier. Der dürfte mit wenigen Änderungen passen.

Ich habe das Problem für einen ATmega Mikrocontroller schon gelösst. Nur 
ich bekomme es nicht hin , den Quellcode an den Xmega anzupassen. Sprich 
den DAC in Betrieb nehmen etc.
Deswegen suche ich am besten einen Source Code  , der schon für einen 
Xmega geschrieben ist.

von Helmut S. (helmuts)


Lesenswert?

Da wird doch einfach 1 Byte an dem Port-D ausgegeben.
out PORTD, R0



Auszug aus der Interrupt Routine:

        lpm                               ; Funktionswert aus dem 
Speicher lesen
        add z1, change1                   ; Phasenakkumulator
        adc z2, change2
        adc z3, change3
        out PORTD, R0                     ; Wert an den 
Analog-Digital-Wandler ausgeben
        out SREG, sregsave                ; Statusregister 
wiederherstellen
        reti                              ; Interrupt verlassen, zurück 
zum Hauptprogramm

von Dani (Gast)


Lesenswert?


von Daniel M. (marcus123)


Lesenswert?

Schonmal danke für deine Hilfe Helmut. Nur ich suche sowas wie in dem 
Link, den ich gepostet habe. Will nämlich auch deswegen einen Xmega 
verwenden um mir den DAC und den Filter zusparen.
Bin auch gerne bereit das Problem irgendwie gemeisam zu lösen(Nachhilfe 
, Dienstleistung etc). Weil alleine werde ich es wahrscheinlich nicht 
hinbekommen.

von Helmut S. (helmuts)


Lesenswert?

Den 8bit D/A-Wandler kannst du mit jedem Controller durch Timer mit PWM 
ersetzen. Einfach auf die Timer-Periode den Interrupt setzen und dann in 
jedem Interrupt einen neuen PWM-Wert laden. Um das Filter am Ausgang 
kommst du aber nicht herum. Im einfachsten Fall ist das ein Widerstand 
und ein Kondensator, wenn deine PWM-Frequenz über 30kHz liegt. Die 
Hauptfilterung erledigt dann dein Lautsprecher und dein Gehör.

von Dani (Gast)


Lesenswert?

Daniel M. schrieb:
> Schonmal danke für deine Hilfe Helmut. Nur ich suche sowas wie in dem
> Link, den ich gepostet habe. Will nämlich auch deswegen einen Xmega
> verwenden um mir den DAC und den Filter zusparen.

Beitrag "Re: Suche Xmega Sinus Quellcode"

von Helmut S. (helmuts)


Lesenswert?

Ich habe keinen XMEGA.


Dein Programmablauf sieht ungefähr so aus.

Haupt-Programm:

Sinustabelle anlegen 1kByte
Variable mit 32 bit für Phase und Frequenz initialisieren.
Timer-Interrupt initialisieren.
Fertig: Endlosschleife, Goto Fertig


PWM-Timer-interrupt:

Obere 10bit von Phase als Zeiger auf das 1KByte RAM nehmen.
Damit 8bit Sinus-Wert aus Tabelle holen.
Wert ins PWM-Register laden.

Phase = Phase+Frequenz

Tasten abfragen

Ende Interrupt

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Helmut S. schrieb:
> Den 8bit D/A-Wandler kannst du mit jedem Controller durch Timer mit PWM
> ersetzen.

Wozu? Xmegas haben eingebaute DACs. Die kann man sogar per DMA mit den 
auszugebenden Werten füttern.

von Helmut S. (helmuts)


Lesenswert?

@Hannes
Danke, hatte mir nie ein Datenblatt von denen wirklich angeschaut.
Wenn die einen DAC haben, um so besser. Dann kann man mit der 
Ausgabefrequenz natürlich höher gehen, falls die DACs schnell genug 
einschwingen.

von Daniel M. (marcus123)


Lesenswert?

Das habe ich auch schon in einem Beispiel gesehen.
1
#include <stdio.h>
2
#include <avr\io.h>
3
#define F_CPU 32000000UL
4
#include <util\delay.h>
5
#include <math.h>
6
7
void GenerateArbWave12(int *data, int len, unsigned long int freq);
8
void SetWaveFreq(unsigned long int freq);
9
void LoadSineWave(int len);
10
void Config32MHzClock(void);
11
12
volatile int data12[100];
13
volatile int gWaveNumSamp=50;
14
15
int main(void)
16
{
17
  int Reading;
18
19
  Config32MHzClock();
20
21
  CLK.PSCTRL = 0x00; // no division on peripheral clock
22
23
  PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_PE7_gc;
24
  PORTE.DIR = (1<<7); // clkout
25
  TCC0.CTRLA = 4;
26
27
// setup DAC output on PORTB:1 as GND reference
28
  PORTB.DIR |= 0x02;
29
  PORTB.OUT &= 0xFD;
30
31
// setup ADC input on PORTA:0-3 (0=hi, 1=hi, 2=samp, 3=gnd)
32
// and power PORTA:1 to create voltage divider
33
  PORTA.DIR = 0xB;
34
  PORTA.OUT = 0x3;
35
36
// setup adc for single ended one shot mode
37
  ADCA.CTRLA |= 0x1;       // enable adc
38
  ADCA.CTRLB = 0x4;        // set 8 bit conversion
39
  ADCA.CH0.CTRL = 0x1;     // single ended
40
  ADCA.CH0.MUXCTRL = 0x10; // PORTA:2
41
  ADCA.REFCTRL = 0x20;     // reference is PORTA:0
42
  ADCA.PRESCALER = 0x5;    // peripheral clk/128
43
44
  LoadSineWave(gWaveNumSamp);
45
46
  // startup in 10kHz
47
  GenerateArbWave12(data12,gWaveNumSamp*2,10000);
48
49
  while(1)
50
  {
51
  // read adc to determine waveform freq
52
    ADCA.CTRLA |= 0x4;               // start conversion ch0
53
    while(!ADCA.CH0.INTFLAGS);       // wait for conversion complete flag
54
    ADCA.CH0.INTFLAGS = 0;           // clear int flags  
55
  Reading = ADCA.CH0RESL;          // read 8 bit value from POT
56
    SetWaveFreq((Reading*Reading)+1); // set freq
57
    _delay_ms(100); 
58
  };
59
  
60
};
61
62
void LoadSineWave(int len)
63
{
64
int i;
65
66
  for(i=0;i<len;i++)
67
  {
68
    data12[i]=((sin((2.0/(float)len)*(float)i*M_PI)*0.5 + 0.5)*4095);
69
  };
70
71
};
72
73
void SetWaveFreq(unsigned long int freq)
74
{
75
    TCD0.PER = F_CPU/freq/gWaveNumSamp/4;
76
};
77
78
void GenerateArbWave12(int *data, int len, unsigned long int freq)
79
{
80
81
EVSYS.CH1MUX = 0xD0;    // CH1 = TCD0 overflow
82
TCD0.CTRLA = 0x03;      // Prescaler: clk/4
83
TCD0.PER   = F_CPU/(len/2)/freq/4;        // 31=1MHz,63=500K,127=250K
84
DACB.CTRLA = 0x05;      // Enable DACB and CH0
85
DACB.CTRLB = 0x01;  // CH0 auto triggered by an event (CH1)
86
DACB.CTRLC = 0x08;  // Use AVCC (3.3V), left adjust
87
DACB.EVCTRL = 0x01; // Event CH1 triggers the DAC Conversion
88
DACB.TIMCTRL = 0x50;// Minimum 32 CLK between conversions
89
DMA.CTRL = 0x80;    // Enable, single buffer, round robin
90
DMA.CH0.ADDRCTRL = 0xD9;// Reload, Increment source
91
DMA.CH0.TRIGSRC= 0x25;  // DACB CH0 is trigger source
92
DMA.CH0.TRFCNT = len;   // Buffer is len bytes
93
DMA.CH0.SRCADDR0  =(((uint32_t)data)>>0*8) & 0xFF;
94
DMA.CH0.SRCADDR1  =(((uint32_t)data)>>1*8) & 0xFF;
95
DMA.CH0.SRCADDR2  =(((uint32_t)data)>>2*8) & 0xFF;
96
DMA.CH0.DESTADDR0 =(((uint32_t)(&DACB.CH0DATA))>>0*8)&0xFF;
97
DMA.CH0.DESTADDR1 =(((uint32_t)(&DACB.CH0DATA))>>1*8)&0xFF;
98
DMA.CH0.DESTADDR2 =(((uint32_t)(&DACB.CH0DATA))>>2*8)&0xFF;
99
DMA.CH0.CTRLA = 0xA5;   // Enable, repeat, 1 byte, single 
100
};
101
102
103
104
void Config32MHzClock(void)
105
{
106
  CCP = CCP_IOREG_gc; //Security Signature to modify clock 
107
  // initialize clock source to be 32MHz internal oscillator (no PLL)
108
  OSC.CTRL = OSC_RC32MEN_bm; // enable internal 32MHz oscillator
109
  while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator ready
110
  CCP = CCP_IOREG_gc; //Security Signature to modify clock 
111
  CLK.CTRL = 0x01; //select sysclock 32MHz osc
112
//  CCP = CCP_IOREG_gc;
113
//  CLK.PSCTRL = 0x02; // peripheral clk = sysclk/4, forces sys also /4??
114
};

Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür 
hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt 
möglich das ohne Poti zu realisieren?Dabei bräuchte ich dringend hilfe. 
Derjenige der mir helfen kann/will kann mir auch eine Email schreiben, 
um gegebenfalls üder die Bezahlung zu sprechen.

von Helmut S. (helmuts)


Lesenswert?

Ein Poti plus ADC ist eine schlechte Lösung. Da springt ja dauend der 
ADC-Wert ein paar bit hin und her.
Nimm 4 Taster als Eingabe und lies die über je einen Port-pin ein.
Damit kannst du die Frequenz-Stelle auswählen und die angwählte Stelle 
rauf- und runterzählen.

von Robert L. (robi-wan)


Lesenswert?

Naja, dann musst du die AD-Wandlung rausnehmen und deine Routine zum 
Setzen der Variable "Reading" einfügen.

von Dani (Gast)


Lesenswert?

Daniel M. schrieb:
> Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür
> hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt
> möglich das ohne Poti zu realisieren?Dabei bräuchte ich dringend hilfe.
> Derjenige der mir helfen kann/will kann mir auch eine Email schreiben,
> um gegebenfalls üder die Bezahlung zu sprechen.

Mal ne doofe Frage: Wie hast Du das Problem eigentlich für einen 
normalen ATMega gelöst? Es gab hier genügend Verweise auf Sourcecode für 
den DAC, mit ohne ohne DMA, mit oder ohne externer Frequenzeinstellung.

von UR Schmitt (Gast)


Lesenswert?

Hallo Helmut,
wo nimmst du eigentlich deine Geduld her?
Der Kerl hat überhaupt kein Interesse irgendwas selbst zu programmieren 
und dabei zu lernen. Bei dem besteht "porgrammieren" nur aus Zeug im 
Internet zusammanzukopieren und irgendwie zum laufen zu bringen. Wenns 
nicht läuft findet man schon einen Dummen ders für einen richtet.
Das ist echt unerträglich.

von Daniel M. (marcus123)


Lesenswert?

Ich müsste ja irgendwie die Werte des Potis für die beiden Frequenzen 
(20 und 22khz)festlegen oder?
weil die Frequenz wird in folgender Methode übergeben.
GenerateArbWave12(data12,gWaveNumSamp*2,10000) zb. für 10khz

von Karl H. (kbuchegg)


Lesenswert?

Daniel M. schrieb:


> Nur wird hier die Frequenzeinstellung über ein Poti erreicht. Dafür
> hätte ich gerne zwei Variablen in dem Quelltext. Ist es überhaupt
> möglich das ohne Poti zu realisieren?

Das ist jetzt aber nicht dein Ernst, oder?

Nach 10 Sekunden den Code überfliegen, fällt mir diese Funktion hier auf
1
void SetWaveFreq(unsigned long int freq)
2
{
3
    TCD0.PER = F_CPU/freq/gWaveNumSamp/4;
4
};
Was denkst du wohl was diese Funktion, dem Namen nach machen wird?


Hast du dir den Code JEMALS auch nur IRGENDWIE angesehen?
Normalerweise sollte man das ausdrucken und dir um die Ohren pfeffern 
bis nur noch Konfetti übrig sind.

> weil die Frequenz wird in folgender Methode übergeben.
> GenerateArbWave12(data12,gWaveNumSamp*2,10000) zb. für 10khz

Genau.
Drum wird das auch in der Hauptschleife nach dem Auslesen das ADC 
aufgerufen.
1
  while(1)
2
  {
3
  // read adc to determine waveform freq
4
    ADCA.CTRLA |= 0x4;               // start conversion ch0
5
    while(!ADCA.CH0.INTFLAGS);       // wait for conversion complete flag
6
    ADCA.CH0.INTFLAGS = 0;           // clear int flags  
7
  Reading = ADCA.CH0RESL;          // read 8 bit value from POT
8
    SetWaveFreq((Reading*Reading)+1); // set freq
9
    _delay_ms(100); 
10
  };

Wo war nochmal genau der Aufruf von GenerateArbWave12? Und warum 
erinnert mich GenerateArbWave12 so ungemein an "Generate Arbitrary 
Wave", also das Erzeugen einer Wavetable.

von Daniel M. (marcus123)


Lesenswert?

Der Aufruf ist vor der Hauptschleife. Wenn ich den Code verstanden hätte 
und ändern könnte würde ich es ja machen und nicht hier nach Hilfe 
ringen.
Also müsste reading auf einen festen Wert setzen werden , weil damit die 
Frequenz gesetzt wird. Und danach wird erst die Werte Tabelle der 
jeweiligen frequenz angelegt oder?

von Helmut S. (helmuts)


Lesenswert?

> Hallo Helmut,
> wo nimmst du eigentlich deine Geduld her?

Na ja, irgendwie muss man sein Wissen ja los werden. :-)
Das Wichtigste ist jetzt eigentlich gesagt werden. Der Rest ist 
Implementierung.
OK, das ganze Bedienungskonzept muss der Fragesteller natürlich auch 
noch definieren und implementieren.

Immerhin bietet er ein paar Euro wenn ihm jemand hilft. Ich kann ihm da 
allerdings nicht weiterhelfen, da ch keinen XMEGA habe.

von Karl H. (kbuchegg)


Lesenswert?

UR Schmitt schrieb:
> Hallo Helmut,
> wo nimmst du eigentlich deine Geduld her?
> Der Kerl hat überhaupt kein Interesse irgendwas selbst zu programmieren
> und dabei zu lernen. Bei dem besteht "porgrammieren" nur aus Zeug im
> Internet zusammanzukopieren und irgendwie zum laufen zu bringen. Wenns
> nicht läuft findet man schon einen Dummen ders für einen richtet.
> Das ist echt unerträglich.

Leider zu spät gelesen.
Offenbar ist dir Daniel M schon öfter aufgefallen.
Den Namen werd ich mir merken.

von Karl H. (kbuchegg)


Lesenswert?

Daniel M. schrieb:
> Der Aufruf ist vor der Hauptschleife. Wenn ich den Code verstanden hätte
> und ändern könnte würde ich es ja machen und nicht hier nach Hilfe
> ringen.

Wenn du nicht programmieren kannst und auch keine Anstalten zeigst es zu 
lernen, wozu dann der Aufwand. Kauf dir Manpower ein und gut ists.

Du bist genau von der Sorte, bei der man absolut die Lust verliert zu 
helfen und sich fragt, wozu man eigentlich Jahre investiert hat um 
dorthin zu kommen wo man ist.

von Daniel M. (marcus123)


Lesenswert?

Ich denke schon,dass ich Anstalten mache es zu verstehen. Zu mindest im 
Rahmen meiner Möglichkeiten, die wohl eher begrenzt sind. Aber ich muss 
dieses Problem ja irgendwie lösen.

Ich bin ja auf der Suche nach Manpower,weil ich es selber nicht 
hinbekomme.
Dann habe ich den Tipp bekommen es mal hier zu versuchen und Ich sehe 
das sich einige mit der Materie auskennen.

Nur egal ob Nachhilfe Lehrer oder in diversen Informatiker Foren habe 
ich bisher noch keine Hilfe finden können. Deswegen sagte ich ja , wer 
mir Helfen kann , muss dies auch nicht Umsonst tuen. Wenn ich hier 
niemanden finde, wüsste ich nicht mehr wo ich suchen sollte.

von Daniel M. (marcus123)


Lesenswert?

Aber zu meiner Verwunderung muss ich feststellen , dass ich es nach 
deinen Denkanstößen geschafft habe, ein 20khz signal zu erzeugen.

von Rudi D. (rulixa)


Lesenswert?

Daniel M. schrieb:
> Hallo liebes Forum,
> ich suche einen Quellcode für einen Xmega der einen Sinus erzeugt.
> Am besten wäre ein Quellcode , in dem die Frequenz eingestellt werden
> kann. Also nicht von aussen über ein Poti oder so.
>
> Hoffe das Ihr mir weiterhelfen könnt.

genügt das? Kann man sicher auf xmega portieren.
http://elektronik-labor.de/AVR/DDSGenerator.htm

von Karl H. (kbuchegg)


Lesenswert?

Daniel M. schrieb:
> Ich denke schon,dass ich Anstalten mache es zu verstehen.

Sorry. Aber da werd ich pampig.
Wenn im Code eh schon alles da ist und sogar die Funktionsnamen so sind, 
dass man das rein durch lesen schon fast im Klartext lesen kann, dann 
KANNST du dir das Programm nicht angesehen haben.
Du hast einfach nur den Code von irgendwo geklaut und HILFE gerufen.

Ich kann auch keinen XMEGA programmieren und 90% der ganze Zuweisungen 
zu den Registern sagen mir überhaupt nichts. Aber ich erkenne eine 
Funktion, wenn ich eine sehe und ich schau mir ihren Namen an und denk 
mir: Was will mir wohl der Autor mit diesem Funktionsnamen sagen.

Und genau das gleiche kann jeder machen, der auch nur die banalsten 
Grundlagen von C ein wenig studiert hat.

von Daniel M. (marcus123)


Lesenswert?

Ok das habe ich verstanden. Wie und wo ich die frequenz ändern kann , 
bekomm ich jetzt auch irgendwie hin.
Hätten Sie denn vl noch einen Tipp wo ich Manpower bekommen könnte?
Trotzdem vielen Dank für ihre Hilfe

von Daniel M. (marcus123)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich bin jetzt soweit das ich die frequenz und die anzahl der Perioden 
einstellen kann. Was mir jetzt noch Probleme bereit, ist die FSK 
modulation.
Kann mir jemand einen Tipp geben?

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.