Get Adobe Flash player
Banner

Xmega Tutorial - Sinus

Benutzerbewertung: / 4
SchwachPerfekt 

xmega_block_diagram3D

Möchte man mit einem Xmega ein Sinussignal generieren, so kann man das am einfachsten über eine feste im Speicher des Controllers hinterlegte Sinustabelle, einem Timer und einer PWM Einheit des Controllers realisieren.

Prinzip

In der Sinustabelle ist eine komplette Sinusschwingung hinterlegt. Dazu wurde mit einer horizontalen festen Schrittweite die einzelnen Spannungswerte mit einer vertikalen Auflösung von 256 Werten berechnet. Gibt man diese Werte nacheinander mit einer festen Frequenz über ein PWM Modul mit einer Auflösung des Tastverhältnisses von 8Bit, also 256 Schritten aus, so würde sich dieses Tastverhältnis in Abhängigkeit dieser Sinuskurve ändern. Da der Xmega mit einer Spannung von 3,3V betrieben wird, entspricht die Amplitude der Sinusschwingung +/- 1,65 V , wobei bei 1,65V (Tabellenwert 127) der virtuelle Nullpunkt liegt. Die Ausgabegeschwindigkeit wird über die im Timer eingestellte Frequenz eingestellt. Je höher diese Frequenz gewählt wird, desto höher wird die Frequenz der Sinusschwingung.

Die Sinuskurve in der Tabelle beginnt bei 127, was dem Wert 0 entspricht (1,65V). Dann steigt der Verlauf an, hat bei 255 (3,3V) sein Maximum, fällt wieder, geht durch 127 (1,65V), erreicht dann das Minimum von 0 (0,0V) und steigt dann wieder an bis der Ausgangspunkt bei 128(1,65V) erreicht wird. Nach diesem Durchgang startet der ganze Vorgang wieder von vorn mit einer neuen Schwingung.

Das erzeugte sinusförmige PWM Signal wird anschließend mit Hilfe von einem Tiefpass, also einem RC-Glied glättet wordurch man eine analoge Sinusspannung erhält.

3-Phasen Sinusgenerator

Möchte man 3 in ihrer Phase verschobene Sinussignale generieren so geht das ganze nach dem gleichen Grundprinzip wie bei einem einfachen Sinussignal. Die weiteren Signale werden ebenfalls über zwei weiter PWM Einheiten erzeugt. Das schöne bei den Xmegas ist , dass man mit einem PWM Modul bis zu 4 PWMs, mit unterschiedlichen Tastverhältnissen erzeugen kann. Alle diese PWMs haben jedoch die gleich Taktquelle wodurch diese synchron laufen. Man muss jetzt nur noch dafür sorgen, dass statt nur einem PWM jeweils alle 3 PWM gleichzeitig aktualisiert werden. Die Verschiebung erhält man, indem alle 3 PWM Signale bei einem anderem Wert in der Sinustabelle starten, siehe folgendes Beispiel.

Xmega Tutorial - 3-Phasen Sinusgenerator
//############### Sinus Setup
#define TIMERRELOAD 256 // Nachladewert des Timers 255
#define AUFLOESUNG 65536 // 16-Bit Counter 65535
const uint8_t sinustabelle[512] PROGMEM = {127,130,133,136,139,143,146,
149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,
203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,
240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,
254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,
240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,
203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,
149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,
87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,
25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,
1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,
44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,
111,115,118,121,124,130,133,136,139,143,146,149,152,155,158,161,164,167,170,
173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,
221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,
249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,
252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,
227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,
181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,
124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,
56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,
7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,
16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,
73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};
 
volatile union {uint16_t u16; uint8_t u8[2];} counterA;
volatile uint16_t offset;
 
//######################################################### 
void sinus_setFreq(int Ausgabefrequenz)
{
 offset=((F_CPU/2+Ausgabefrequenz*TIMERRELOAD*AUFLOESUNG)/F_CPU); 
 /* F_CPU/2 fürs Runden */
}
//######################################################### 
void sinus_init(void)
{
 sbi(PORTF.DIR,0); // Ausgang
 sbi(PORTF.DIR,1); // Ausgang
 sbi(PORTF.DIR,2); // Ausgang
 /* Modus BIT0/1=Single Slope PWM BIT4=OCA, BIT5=OCB Enable */
 TCF0.CTRLA = TC_CLKSEL_DIV1_gc; // Prescaler 1
 TCF0.CTRLB = 0b11110011; 
 TCF0.PER = 0x00ff; // Top-Wert 65xxx 
 TCF0.CNT = 0x00; // Zähler zurücksetzen
 TCF0.INTCTRLA = 0b00000011; // Interrupt konfigurieren
 
 TCF0.CCA = 100; // PWM Auflösung 256
 TCF0.CCB = 100;
 TCF0.CCC = 100;
 
 counterA.u16=0;
}
//######################################################### Int Timer F0
ISR(TCF0_OVF_vect)
{
 TCF0.CCA = pgm_read_byte(&sinustabelle[counterA.u8[1]+ 0]);
 TCF0.CCB = pgm_read_byte(&sinustabelle[counterA.u8[1]+ 85]);
 TCF0.CCC = pgm_read_byte(&sinustabelle[counterA.u8[1]+171]);
 counterA.u16 += offset; 
}
//######################################################### Main
int main (void) 
{ 
 cli(); // Interrupts deaktivieren
 sinus_init();
 //Interrupts (Highlevel,Mediumlevel und Lowlevel freigeben) 
 PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
 sei(); // Interrupts aktivieren 
 
 sinus_setFreq(150); 
 
 while(1) 
 { 
 }
} 

Hinweis:
Das Tutorial wird nach und nach von mir ergänzt. Wenn ihr Fehler in dem Tutorial findet, würde ich mich freuen wenn ihr mir diese mitteilt, damit ich diese korrigieren kann. Wenn jemand eigene Tips, Informationen oder Code-Schnipsel hat kann er mir diese gern zusenden, damit ich sie anschließend in das Tutorial einbinden kann.

Links und Downloads


Kommentare  

 
0 # Steffen Epple 2012-10-28 11:18
Hallo Martin,
kleiner Hinweis: X-mega Tutorial Kapitel Sinus, Unterkapitel "Prinzip", 2.Absatz Zeile3:
..."steigt dann wieder an bis der Ausgangspunkt bei 64 (1,65V) erreicht wird."

müsste es nicht 128 statt 64 heißen?

MFG
S.
P.S:Glückwunsch zu dem gelungenen Tutorial.
Antworten | Antworten mit Zitat | Zitieren
 
 
0 # admin 2012-10-28 13:28
Hallo Steffen,
vielen Dank für den Hinweis. Wurde so eben korrigiert.
Martin
Antworten | Antworten mit Zitat | Zitieren
 

Kommentar schreiben


Sicherheitscode
Aktualisieren

Was verwendet Ihr?
 

Neue Beiträge

16 Juni 2013
Folgend gibt es ein kleines Beispiel wie man über den SPI-Bis dess Xmegas mit einer SD Karte kommunizieren...
15 Juni 2013
Bei den Xmega Controllern hat sich auch am Interruptsystem so einiges geändert. Das System ist im Vergleich zu...
15 Juni 2013
Neben den standard Timer/Counter Modulen bringen die Xmega-COntroller auch einen Realtimecounter mit. In ...
15 Juni 2013
Mit Hilfe des I2C/ TWI Moduls des Xmegas kann den Ultraschall Entfernungsmesser SRF02 auslesen. Dieser ist...
24 Mai 2013
Vor kurzem ist mein erstem kleines Rennboot fertig geworden. Vom Typ gehört das Boot zur Familie der...
14 Mai 2013
Für den Aufbau eine Laserbank oder die präzise Ablenkung eines Laserstrahls benötigt man neben den speziellen...