Inhoudsopgave:

3-fasen sinusgenerator op basis van Arduino Due - Ajarnpa
3-fasen sinusgenerator op basis van Arduino Due - Ajarnpa

Video: 3-fasen sinusgenerator op basis van Arduino Due - Ajarnpa

Video: 3-fasen sinusgenerator op basis van Arduino Due - Ajarnpa
Video: How an Alternators work | How 3 phase Electricity produce | Generator working principle brushless 2024, November
Anonim
3-fasen sinusgenerator op basis van Arduino Due
3-fasen sinusgenerator op basis van Arduino Due

het doel van dit aandeel is om iemand te helpen die de betere prestaties van Due probeert te gebruiken + gebrek aan referentie + niet-nuttige datasheet.

dit project is in staat om tot 3 fase sinusgolf @ 256 samples/cyclus bij lage freq (<1kHz) en 16 samples/cyclus @ hoge freq (tot 20kHz) te genereren, wat goed genoeg is om te worden afgevlakt door eenvoudige LPF's en de uitvoer is bijna perfect.

het bijgevoegde bestand was niet mijn definitieve versie, want ik heb een extra functie toegevoegd, maar de kern is hetzelfde. Merk op dat de monsters/cyclus lager was ingesteld dan de bovenstaande verklaring.

aangezien de CPU-capaciteit wordt gemaximaliseerd door de benadering die wordt getoond in het bijgevoegde bestand, heb ik een Arduino Uno als besturingseenheid gebruikt, die de externe interrupt van Arduino Due gebruikt om de frequentiewaarde door te geven aan Arduino Due. Naast frequentieregeling regelt de Arduino Uno ook de amplitude (via digitale potentiaalmeter + OpAmp) en I/O --- er zal veel ruimte zijn om mee te spelen.

Stap 1: Genereer sinusgegevensarray

Aangezien real-time berekening CPU-veeleisend is, is een sinusgegevensarray vereist voor betere prestaties

uint32_t sin768 PROGMEM= ….terwijl x=[0:5375]; y = 127+127*(sin(2*pi/5376/*of een # die u verkiest, hangt af van de vereiste*/))

Stap 2: Parallelle uitvoer inschakelen

In tegenstelling tot Uno heeft Due een beperkte referentie. Om echter een 3-fase sinusgolf te genereren op basis van Arduino Uno, ten eerste, zijn de prestaties niet te applaudisseren vanwege de lage MCLK (16 MHz terwijl Due 84 MHz is), ten tweede is het beperkt GPIO kan max. 2-fasen output produceren en je hebt extra nodig analoge schakeling om de 3e fase (C=-AB) te produceren.

Het inschakelen van GPIO was meestal gebaseerd op proberen en proberen + niet nuttig gegevensblad van SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; //PIO-controller PIO Enable register (zie p656 van ATMEL SAM3X datasheet) en https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 en 44-51 waren ingeschakeld

PIOC->PIO_OER = 0xFFFFFFFE; // PIO-controller uitgang inschakelen register, zie p657 van ATMEL SAM3X datasheet PIOC->PIO_OSR = 0xFFFFFFFE; //PIO-controller output statusregister, zie p658 van ATMEL SAM3X datasheet

PIOC->PIO_OWER = 0xFFFFFFFE; // PIO-uitgang schrijf-enabled register, zie p670 van ATMEL SAM3X datasheet

//PIOA->PIO_PDR = 0x30000000; // optioneel als verzekering, lijkt de prestaties niet te beïnvloeden, digitale pin 10 maakt verbinding met zowel PC29 als PA28, digitale pin 4 maakt verbinding met zowel PC29 als PA28, hier om PIOA #28 & 29 uit te schakelen

Stap 3: Onderbreking inschakelen

Om de prestaties te maximaliseren, moet de CPU-belasting zo laag mogelijk zijn. Vanwege de niet-op-1-correspondentie tussen de CPU-pin en de Due-pin is bitbewerking echter noodzakelijk.

Je kunt het algoritme verder optimaliseren maar de ruimte is erg beperkt.

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

t = t% monsters; // gebruik t%samples in plaats van 'if' om overloop van t. te voorkomen

phaseAInc = (preset*t)%5376; // gebruik %5376 om overloop van de array-index te voorkomen

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; //verwijs naar PIOC: PC1 tot PC8, corresponderende Arduino Due pin: pin 33-40, vandaar naar links schuiven voor 1 cijfer

p_B = sin768[phaseBInc]<<12; // verwijzen naar PIOC: PC12 tot PC19, overeenkomstige Arduino Due pin: pin 51-44, vandaar shift links 12 cijfers

p_C = sin768[phaseCInc]; //fase C uitgang werknemer PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 en PC29, bijbehorende Arduino Due pin: digitale pin: 9, 8, 7, 6, 5, 4, 3, 10, respectievelijk

p_C2 = (p_C&B11000000)<<22; //dit genereert PC28 en PC29

p_C3 = (p_C&B00111111)<<21; //dit genereert PC21-PC26

p_C = p_C2|p_C3; // dit genereert parallelle output van fase C

p_A = p_A|p_B|p_C; //32 bit output = fase A (8bit)|fase B|fase C

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

t++; }

Stap 4: R/2R DAC

bouw 3x8bit R/2R DAC, veel ref op google.

Stap 5: Volledige 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; // fase A fase B fase C-waarde - hoewel de uitvoer alleen 8 bits is, zullen de p_A- en p_B-waarde worden gebruikt om een nieuwe 32-bits waarde te genereren om met 32-bits PIOC-uitvoer om te gaan

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t-interval; uint16_t voorbeelden, vooraf ingesteld; uint32_t t = 0;

ongeldige setup() {

//parallelle output PIOC setup: Arduino Due pin33-40 wordt gebruikt als fase A-uitgang, terwijl pin 44-51 werkt voor fase B-uitgang

PIOC->PIO_PER = 0xFFFFFFFE; //PIO-controller PIO Enable register (zie p656 van ATMEL SAM3X datasheet) en https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 en 44-51 waren ingeschakeld

PIOC->PIO_OER = 0xFFFFFFFE; // PIO-controller uitgang inschakelen register, zie p657 van ATMEL SAM3X datasheet

PIOC->PIO_OSR = 0xFFFFFFFE; //PIO-controller output statusregister, zie p658 van ATMEL SAM3X datasheet

PIOC->PIO_OWER = 0xFFFFFFFE; // PIO-uitvoer schrijf-enabled register, zie p670 van ATMEL SAM3X datasheet

//PIOA->PIO_PDR = 0x30000000; //optioneel als verzekering, lijkt de prestaties niet te beïnvloeden, digitale pin 10 verbindt met zowel PC29 als PA28, digitale pin 4 maakt verbinding met zowel PC29 als PA28, hier om PIOA #28 & 29 uit te schakelen //timer setup, zie https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect(false); // schrijfbeveiliging van Power Management Control-registers uitschakelen

pmc_enable_periph_clk(ID_TC7); // schakel perifere kloktijdteller 7. in

TC_Configure(/* klok */TC2, /* kanaal */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //TC klok 42MHz (klok, kanaal, vergelijk modus instelling) TC_SetRC (TC2, 1, interval); TC_Start(TC2, 1);

// schakel timeronderbrekingen in op de timer TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = interrupt inschakelen register TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = interrupt uitschakelen register

NVIC_EnableIRQ(TC7_IRQn); // Schakel de interrupt in de geneste vector interruptcontroller in freq = 60; // initialiseer frequentie als 60 Hz preset = 21; // matrixindexverhoging met 21 samples = 256; //output samples 256/cyclus interval = 42000000/(freq*samples); //onderbreking telt TC_SetRC (TC2, 1, interval); //start TC Serial.begin (9600); //voor testdoeleinden}

ongeldige checkFreq()

{ freqNieuw = 20000;

if (freq == freqNieuw) {} else

{ freq = freqNieuw;

als (freq>20000) {freq = 20000; /*max frequentie 20kHz*/};

als (freq<1) {freq = 1; /*min frequentie 1Hz*/};

if (freq>999) {preset = 384; samples = 14;} // voor frequentie >=1kHz, 14 samples voor elke cyclus

else if (freq>499) {preset = 84; samples = 64;} // voor 500<=frequentie99) {preset = 42; samples = 128;} //voor 100Hz<=frequentie<500Hz, 128 samples/cyclus

anders {voorinstelling = 21; monsters = 256;}; // voor frequentie <100 hz, 256 monsters voor elke cyclus

interval = 42000000/(freq*samples); t = 0; TC_SetRC(TC2, 1, interval); } }

lege lus() {

checkFreq(); vertraging (100); }

ongeldig TC7_Handler (ongeldig)

{ TC_GetStatus(TC2, 1);

t = t% monsters; // gebruik t%samples om overloop van t phaseAInc = (preset*t)%5376 te voorkomen; // gebruik %5376 om overloop van de array-index te voorkomen

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; //verwijs naar PIOC: PC1 tot PC8, corresponderende Arduino Due pin: pin 33-40, vandaar naar links schuiven voor 1 cijfer

p_B = sin768[phaseBInc]<<12; //verwijs naar PIOC: PC12 tot PC19, corresponderende Arduino Due pin: pin 51-44, vandaar shift links 12 cijfers

p_C = sin768[phaseCInc]; //fase C uitgang werknemer PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 en PC29, bijbehorende Arduino Due pin: digitale pin: 9, 8, 7, 6, 5, 4, 3, 10, respectievelijk

p_C2 = (p_C&B11000000)<<22; //dit genereert PC28 en PC29

p_C3 = (p_C&B00111111)<<21; //dit genereert PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2|p_C3; // dit genereert parallelle output van fase C

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

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

Aanbevolen: