Sadržaj:

Generator trofaznih sinusnih valova baziran na Arduinu Due: 5 koraka
Generator trofaznih sinusnih valova baziran na Arduinu Due: 5 koraka

Video: Generator trofaznih sinusnih valova baziran na Arduinu Due: 5 koraka

Video: Generator trofaznih sinusnih valova baziran na Arduinu Due: 5 koraka
Video: Function Generator: Amplitude, Frequency, DC Offset Settings, Available Buttons, Signal Output 2024, Juli
Anonim
Generator trofaznih sinusnih valova baziran na Arduino Due
Generator trofaznih sinusnih valova baziran na Arduino Due

svrha ovog udjela je pomoći nekome tko pokušava iskoristiti Due-ove bolje performanse + nedostatak referenci + nepotrebnu tablicu podataka.

ovaj projekt je u stanju generirati do 3 fazna sinusna vala @ 256 uzoraka / ciklus pri niskim frekvencijama (<1kHz) i 16 uzoraka / ciklus pri visokim frekvencijama (do 20 kHz), što je dovoljno dobro da se izgladi jednostavnim LPF -ovima i izlaz je gotovo savršen.

priložena datoteka nije bila moja konačna verzija jer sam dodao neku dodatnu značajku, ali jezgra je ista. Imajte na umu da su uzorci/ciklus postavljeni niže od gornje izjave.

budući da je kapacitet procesora maksimiziran pristupom prikazanim u priloženoj datoteci, kao kontrolnu jedinicu koristio sam Arduino Uno, koji koristi vanjski prekid Arduino Due za prosljeđivanje vrijednosti frekvencije na Arduino Due. Osim kontrole frekvencije, Arduino Uno također kontrolira amplitudu (putem digitalnog mjerača potencijala + OpAmp), kao i I/O --- bit će puno prostora za igru.

Korak 1: Generirajte niz sinusnih podataka

Budući da je proračun u stvarnom vremenu zahtjevan za CPU, za bolje performanse potreban je niz sinusnih podataka

uint32_t sin768 PROGMEM =….dok x = [0: 5375]; y = 127+127*(sin (2*pi/5376/*ili neki # koji više volite ovisi o zahtjevu*/))

Korak 2: Omogućavanje paralelnog izlaza

Za razliku od Una, Due imaju ograničene reference. Međutim, kako bi se generirao trofazni sinusni val temeljen na Arduino Uno, prvo, performanse se ne mogu pohvaliti zbog niske MCLK (16 MHz dok je Due 84 MHz), drugo, ograničeni GPIO može proizvesti maksimalno 2 fazni izlaz i trebate dodatni analogno kolo za proizvodnju 3. faze (C = -AB).

Nakon omogućavanja GPIO -a, uglavnom se zasnivalo na isprobavanju i neupotrebljivoj tablici podataka SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO kontroler PIO Enable register (pogledajte str. 656 u podatkovnom listu ATMEL SAM3X) i https://arduino.cc/en/Hacking/PinMappingSAM3X, omogućeni pin 33-41 i 44-51 Arduino Due

PIOC-> PIO_OER = 0xFFFFFFFE; // Registar za omogućavanje izlaza PIO kontrolera, pogledajte p657 tablice podataka ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // Registar statusa izlaza PIO kontrolera, pogledajte p658 podatkovne tablice ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registar za omogućavanje upisivanja PIO izlaza, pogledajte p670 podatkovne tablice ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // Opcionalno kao osiguranje, čini se da ne utječe na performanse, digitalni pin 10 povežite i na PC29 i na PA28, digitalni pin 4 na PC29 i PA28, ovdje za onemogućavanje onemogućavanja PIOA #28 & 29

Korak 3: Omogućavanje prekida

Kako bi se povećale njegove performanse, opterećenje procesora treba biti što je moguće manje. Međutim, zbog korespondencije koja nije 1to1 između CPU pina i Due pina, bitna operacija je neophodna.

Možete dodatno optimizirati algoritam, ali je prostor vrlo ograničen.

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

t = t%uzoraka; // koristite t%uzoraka umjesto 'if' kako biste izbjegli prelijevanje t

phaseAInc = (unapred podešeno*t)%5376; // koristite %5376 da biste izbjegli prelijevanje indeksa polja

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // odnosi se na PIOC: PC1 do PC8, odgovarajući Arduino Due pin: pin 33-40, stoga pomaknite lijevo za 1 znamenku

p_B = sin768 [phaseBInc] << 12; // odnosi se na PIOC: PC12 na PC19, odgovarajući Arduino Due pin: pin 51-44, stoga pomaknite lijevo 12 znamenki

p_C = sin768 [phaseCInc]; // izlaz C faze zaposlenik PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 i PC29, odgovarajući Arduino Due pin: digitalni pin: 9, 8, 7, 6, 5, 4, 3, 10, respektivno

p_C2 = (p_C & B11000000) << 22; // ovo generira PC28 i PC29

p_C3 = (p_C & B00111111) << 21; // ovo generira PC21-PC26

p_C = p_C2 | p_C3; // ovo generira paralelni izlaz faze C

p_A = p_A | p_B | p_C; // 32 bitni izlaz = faza A (8 bit) | faza B | faza C

PIOC-> PIO_ODSR = p_A; // izlazni registar = p_A

t ++; }

Korak 4: R/2R DAC

izgradite 3x8bit R/2R DAC, hrpu preporuka na google -u.

Korak 5: Potpuni kod

#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; // faza A faza B vrijednost C-iako su izlazi samo 8 bita, vrijednosti p_A i p_B će se koristiti za generiranje nove 32-bitne vrijednosti kako bi se kopiralo sa 32-bitnim izlazom PIOC

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t interval; uint16_t uzorci, unaprijed; uint32_t t = 0;

void setup () {

// paralelni izlaz PIOC postavka: Arduino Due pin33-40 se koristi kao izlaz A faze, dok pin 44-51 radi za izlaz B faze

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO kontroler PIO Enable register (pogledajte str. 656 u podatkovnom listu ATMEL SAM3X) i https://arduino.cc/en/Hacking/PinMappingSAM3X, omogućeni pin 33-41 i 44-51 Arduino Due

PIOC-> PIO_OER = 0xFFFFFFFE; // Registar za omogućavanje izlaza PIO kontrolera, pogledajte p657 podatkovne tablice ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // Registar statusa izlaza PIO kontrolera, pogledajte p658 podatkovne tablice ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registar za omogućavanje upisivanja PIO izlaza, pogledajte p670 podatkovne tablice ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // Opcionalno kao osiguranje, čini se da ne utječe na performanse, digitalni pin 10 povežite i na PC29 i na PA28, digitalni pin 4 na PC29 i PA28, ovdje za onemogućavanje onemogućavanja PIOA #28 & 29 // podešavanje tajmera, pogledajte https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (false); // onemogućava zaštitu od upisivanja registara za upravljanje napajanjem

pmc_enable_periph_clk (ID_TC7); // omogućavanje brojača vremena perifernog sata 7

TC_Configure (/ * sat */TC2,/ * kanal */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // TC sat 42MHz (sat, kanal, postavka moda za usporedbu) TC_SetRC (TC2, 1, interval); TC_Start (TC2, 1);

// omogućavanje prekida tajmera na tajmeru TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = registar za omogućavanje prekida TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = registar za onemogućavanje prekida

NVIC_EnableIRQ (TC7_IRQn); // Omogućava prekid u ugniježđenom vektorskom kontroleru prekida freq = 60; // inicijalizira frekvenciju kao 60Hz unaprijed = 21; // povećanje indeksa niza za 21 uzorak = 256; // izlazni uzorci 256/interval ciklusa = 42000000/(frekv.*uzorci); // brojevi prekida TC_SetRC (TC2, 1, interval); // pokretanje TC Serial.begin (9600); // u svrhu testiranja}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} else

{freq = freqNew;

if (freq> 20000) {freq = 20000; /*maksimalna frekvencija 20kHz*/};

if (freq <1) {freq = 1; /*min frekvencija 1Hz*/};

if (frekv.> 999) {preset = 384; uzorci = 14;} // za frekvenciju> = 1 kHz, 14 uzoraka za svaki ciklus

else if (freq> 499) {preset = 84; uzorci = 64;} // za 500 <= frekvencija99) {unaprijed = 42; uzorci = 128;} // za 100Hz <= frekvencija <500Hz, 128 uzoraka/ciklus

else {preset = 21; uzorci = 256;}; // za frekvenciju <100Hz, 256 uzoraka za svaki ciklus

interval = 42000000/(učestali*uzorci); t = 0; TC_SetRC (TC2, 1, interval); }}

void loop () {{100} {101}

checkFreq (); kašnjenje (100); }

void TC7_Handler (void)

{TC_GetStatus (TC2, 1);

t = t%uzoraka; // koristiti t%uzoraka za izbjegavanje prelijevanja t phaseAInc = (unaprijed*t)%5376; // koristite %5376 da biste izbjegli prelijevanje indeksa polja

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // odnosi se na PIOC: PC1 do PC8, odgovarajući Arduino Due pin: pin 33-40, stoga pomaknite lijevo za 1 znamenku

p_B = sin768 [phaseBInc] << 12; // odnosi se na PIOC: PC12 do PC19, odgovarajući Arduino Due pin: pin 51-44, stoga pomaknite lijevo 12 znamenki

p_C = sin768 [phaseCInc]; // izlaz C faze zaposlenik PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 i PC29, odgovarajući Arduino Due pin: digitalni pin: 9, 8, 7, 6, 5, 4, 3, 10, respektivno

p_C2 = (p_C & B11000000) << 22; // ovo generira PC28 i PC29

p_C3 = (p_C & B00111111) << 21; // ovo generira PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // ovo generira paralelni izlaz faze C

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

PIOC-> PIO_ODSR = p_A; // izlazni registar = p_A t ++; }

Preporučuje se: