Inhaltsverzeichnis:

3-Phasen-Sinusgenerator basierend auf Arduino Due - Gunook
3-Phasen-Sinusgenerator basierend auf Arduino Due - Gunook

Video: 3-Phasen-Sinusgenerator basierend auf Arduino Due - Gunook

Video: 3-Phasen-Sinusgenerator basierend auf Arduino Due - Gunook
Video: Tongenerator für Audiotests, Sinusapproximation 2024, Juli
Anonim
3-Phasen-Sinusgenerator basierend auf Arduino Due
3-Phasen-Sinusgenerator basierend auf Arduino Due

Der Zweck dieser Freigabe besteht darin, jemandem zu helfen, der versucht, die höhere Leistung von Due + fehlende Referenz + nicht hilfreiches Datenblatt zu nutzen.

Dieses Projekt ist in der Lage, bis zu 3-Phasen-Sinuswellen @ 256 Abtastungen / Zyklus bei niedriger Frequenz (<1 kHz) und 16 Abtastungen / Zyklus bei hoher Frequenz (bis zu 20 kHz) zu erzeugen, was gut genug ist, um durch einfache LPFs und die. geglättet zu werden Die Ausgabe ist fast perfekt.

Die angehängte Datei war nicht meine endgültige Version, da ich einige zusätzliche Funktionen hinzugefügt habe, aber der Kern ist derselbe. Beachten Sie, dass die Proben/Zyklus niedriger als die obige Aussage eingestellt wurden.

Da die CPU-Kapazität durch den in der angehängten Datei gezeigten Ansatz maximiert wird, habe ich einen Arduino Uno als Steuereinheit verwendet, der den externen Interrupt von Arduino Due nutzt, um den Frequenzwert an Arduino Due zu übergeben. Neben der Frequenzsteuerung steuert der Arduino Uno auch die Amplitude (über digitales Potenzialmeter + OpAmp) sowie I / O - es wird viel Platz zum Spielen geben.

Schritt 1: Sinus-Datenarray generieren

Da Echtzeitberechnungen CPU-Belastungen erfordern, ist für eine bessere Leistung ein Sinusdaten-Array erforderlich

uint32_t sin768 PROGMEM= ….while x=[0:5375]; y = 127+127*(sin(2*pi/5376/*oder einige #, die Sie bevorzugen, hängt von den Anforderungen ab*/))

Schritt 2: Aktivieren des Parallelausgangs

Im Gegensatz zu Uno haben Due nur begrenzte Referenzen. Um jedoch eine 3-Phasen-Sinuswelle basierend auf Arduino Uno zu erzeugen, ist die Leistung erstens aufgrund seines niedrigen MCLK (16 MHz, während Due 84 MHz) nicht applaudiert Analogschaltung zur Erzeugung der 3. Phase (C=-AB).

Die GPIO-Aktivierung basierte hauptsächlich auf Try and Trial + nicht hilfreiches Datenblatt von SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; // PIO-Controller PIO Enable Register (siehe p656 des ATMEL SAM3X Datenblatts) und https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due Pin 33-41 und 44-51 wurden aktiviert

PIOC->PIO_OER = 0xFFFFFFFE; // PIO-Controller-Ausgangsfreigaberegister, siehe p657 des ATMEL SAM3X-Datenblatts PIOC->PIO_OSR = 0xFFFFFFFE; // PIO-Controller-Ausgangsstatusregister, siehe p658 des ATMEL SAM3X-Datenblatts

PIOC->PIO_OWER = 0xFFFFFFFE; // PIO-Ausgangs-Schreibfreigaberegister, siehe p670 des ATMEL SAM3X-Datenblatts

//PIOA->PIO_PDR = 0x30000000; // optional als Versicherung, scheint die Leistung nicht zu beeinträchtigen, digitaler Pin 10 ist sowohl mit PC29 als auch mit PA28 verbunden, digitaler Pin 4 verbindet sich mit PC29 und PA28, hier zum Deaktivieren von PIOA #28 & 29

Schritt 3: Aktivieren der Unterbrechung

Um die Leistung zu maximieren, sollte die CPU-Last so gering wie möglich sein. Aufgrund der Nicht-1-zu-1-Entsprechung zwischen dem CPU-Pin und dem Due-Pin ist jedoch eine Bitoperation erforderlich.

Sie können den Algorithmus weiter optimieren, aber der Raum ist sehr begrenzt.

Void TC7_Handler (void) { TC_GetStatus (TC2, 1);

t = t% Proben; // t%samples anstelle von 'if' verwenden, um einen Überlauf von t zu vermeiden

phaseAInc = (voreingestellt*t)%5376; // Verwenden Sie %5376, um einen Überlauf des Array-Index zu vermeiden

PhaseBInc = (PhaseAInc+1792)%5376;

PhaseCInc = (PhaseAInc+3584)%5376;

p_A = sin768[PhaseAInc]<<1; // siehe PIOC: PC1 bis PC8, entsprechender Arduino Due Pin: Pin 33-40, daher um 1 Stelle nach links verschieben

p_B = sin768[PhaseBInc]<<12; // siehe PIOC: PC12 bis PC19, entsprechender Arduino Due Pin: Pin 51-44, daher 12 Stellen nach links verschieben

p_C = sin768[PhaseCInc]; // Phase-C-Ausgang beschäftigt PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 und PC29, entsprechender Arduino Due-Pin: digitaler Pin: 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C&B11000000)<<22; // dies erzeugt PC28 und PC29

p_C3 = (p_C&B00111111)<<21; // dies erzeugt PC21-PC26

p_C = p_C2|p_C3; // dies erzeugt eine parallele Ausgabe von Phase C

p_A = p_A|p_B|p_C; //32-Bit-Ausgabe = Phase A (8bit)|Phase B|Phase C

PIOC->PIO_ODSR = p_A; //Ausgaberegister =p_A

t++; }

Schritt 4: R/2R-DAC

Build 3x8bit R / 2R DAC, viele Referenzen auf Google.

Schritt 5: Vollständiger Code

#define_BV(x) (1<<(x)); uint32_t sin768 PROGMEM= /* x=[0:5375]; y = 127+127*(sin(2*pi/5376)) */

uint32_t p_A, p_B, p_C, p_C2, p_C3; // Phase A Phase B Phase C-Wert - obwohl die Ausgabe nur 8 Bit beträgt, werden p_A- und p_B-Werte betrieben, um einen neuen 32-Bit-Wert zu generieren, um mit der 32-Bit-PIOC-Ausgabe fertig zu werden

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t-Intervall; uint16_t Samples, voreingestellt; uint32_tt = 0;

Leere Einrichtung () {

// Parallelausgang PIOC-Setup: Arduino Due Pin33-40 werden als Phase-A-Ausgang verwendet, während Pin 44-51 für Phase-B-Ausgang verwendet wird

PIOC->PIO_PER = 0xFFFFFFFE; // PIO-Controller PIO Enable Register (siehe p656 des ATMEL SAM3X Datenblatts) und https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due Pin 33-41 und 44-51 wurden aktiviert

PIOC->PIO_OER = 0xFFFFFFFE; // PIO-Controller-Ausgangsfreigaberegister, siehe p657 des ATMEL SAM3X-Datenblatts

PIOC->PIO_OSR = 0xFFFFFFFE; // PIO-Controller-Ausgangsstatusregister, siehe p658 des ATMEL SAM3X-Datenblatts

PIOC->PIO_OWER = 0xFFFFFFFE; // PIO-Ausgangs-Schreibfreigaberegister, siehe p670 des ATMEL SAM3X-Datenblatts

//PIOA->PIO_PDR = 0x30000000; // optional als Versicherung, scheint die Leistung nicht zu beeinträchtigen, digitaler Pin 10 sowohl mit PC29 als auch PA28 verbinden, digitaler Pin 4 sowohl mit PC29 als auch PA28 verbinden, hier zum Deaktivieren der Deaktivierung von PIOA #28 & 29 // Timer-Setup, siehe https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (falsch); // Schreibschutz der Power Management Control Register deaktivieren

pmc_enable_periph_clk(ID_TC7); // Peripherieuhrzeitzähler aktivieren 7

TC_Configure(/* Uhr */TC2, /* Kanal */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //TC-Takt 42MHz (Takt, Kanal, Vergleichsmoduseinstellung) TC_SetRC (TC2, 1, Intervall); TC_Start (TC2, 1);

// Timer-Interrupts auf dem Timer aktivieren TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = Interrupt-Aktivierungsregister TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = Interrupt-Deaktivierungsregister

NVIC_EnableIRQ(TC7_IRQn); // Aktivieren des Interrupts im verschachtelten Vektor-Interrupt-Controller freq = 60; // Frequenz als 60Hz-Voreinstellung initialisieren = 21; // Erhöhung des Array-Index um 21 Samples = 256; // Ausgabe-Samples 256/Zyklus-Intervall = 42000000/(Freq * Samples); // Interrupt zählt TC_SetRC (TC2, 1, Intervall); // TC Serial.begin (9600) starten; //zu Testzwecken }

void checkFreq()

{ freqNeu = 20000;

if (freq == freqNeu) {} else

{ freq = freqNeu;

wenn (Freq>20000) {Freq = 20000; /*max. Frequenz 20kHz*/};

wenn (Freq < 1) {Freq = 1; /*min Frequenz 1Hz*/};

wenn (Freq>999) {Voreinstellung = 384; Samples = 14;} // für Frequenz > = 1 kHz, 14 Samples für jeden Zyklus

sonst wenn (Freq>499) {Voreinstellung = 84; Samples = 64;} // für 500 <= Frequenz99) {Voreinstellung = 42; Samples = 128;} // für 100Hz<=Frequenz<500Hz, 128 Samples/Zyklus

sonst {Voreinstellung = 21; Proben = 256;}; // für Frequenz < 100 Hz, 256 Abtastungen für jeden Zyklus

Intervall = 42000000/(Häufigkeit*Proben); t = 0; TC_SetRC(TC2, 1, Intervall); } }

Leere Schleife () {

checkFreq(); Verzögerung (100); }

void TC7_Handler(void)

{ TC_GetStatus (TC2, 1);

t = t% Proben; // t%samples verwenden, um einen Überlauf von t zu vermeiden phaseAInc = (preset*t)%5376; // Verwenden Sie %5376, um einen Überlauf des Array-Index zu vermeiden

PhaseBInc = (PhaseAInc+1792)%5376;

PhaseCInc = (PhaseAInc+3584)%5376;

p_A = sin768[PhaseAInc]<<1; // siehe PIOC: PC1 bis PC8, entsprechender Arduino Due Pin: Pin 33-40, daher um 1 Stelle nach links verschieben

p_B = sin768[PhaseBInc]<<12; // siehe PIOC: PC12 bis PC19, entsprechender Arduino Due Pin: Pin 51-44, daher 12 Stellen nach links verschieben

p_C = sin768[PhaseCInc]; // Phase-C-Ausgang beschäftigt PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 und PC29, entsprechender Arduino Due-Pin: digitaler Pin: 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C&B11000000)<<22; // dies erzeugt PC28 und PC29

p_C3 = (p_C&B00111111)<<21; // dies erzeugt PC21-PC26 // Serial.println (p_C3, BIN); p_C = p_C2|p_C3; // dies erzeugt eine parallele Ausgabe von Phase C

p_A = p_A|p_B|p_C; //32-Bit-Ausgabe = Phase A (8bit)|Phase B|Phase C //Serial.println(p_A>>21, BIN); //PIOC->PIO_ODSR = 0x37E00000;

PIOC->PIO_ODSR = p_A; //Ausgaberegister =p_A t++; }

Empfohlen: