Turinys:

3 fazių sinusinių bangų generatorius, pagrįstas „Arduino“terminu: 5 žingsniai
3 fazių sinusinių bangų generatorius, pagrįstas „Arduino“terminu: 5 žingsniai

Video: 3 fazių sinusinių bangų generatorius, pagrįstas „Arduino“terminu: 5 žingsniai

Video: 3 fazių sinusinių bangų generatorius, pagrįstas „Arduino“terminu: 5 žingsniai
Video: Opamp RC fazės poslinkio generatorius – sinusinė banga 2024, Lapkritis
Anonim
3 fazių sinusinių bangų generatorius, pagrįstas „Arduino Due“
3 fazių sinusinių bangų generatorius, pagrįstas „Arduino Due“

šios dalies tikslas yra padėti tam, kuris bando panaudoti didesnį „Due“našumą + nuorodos trūkumą ir nenaudingą duomenų lapą.

šis projektas gali generuoti iki 3 fazių sinusinių bangų @ 256 mėginius per ciklą esant žemam dažniui (<1 kHz) ir 16 mėginių per ciklą @ dideliam dažniui (iki 20 kHz), o tai yra pakankamai gerai, kad būtų galima išlyginti paprastais LPF ir išvestis beveik tobula.

pridėtas failas nebuvo mano galutinė versija, nes pridėjau papildomos funkcijos, tačiau esmė yra ta pati. Atkreipkite dėmesį, kad mėginiai/ciklas buvo nustatyti žemesni nei aukščiau.

Kadangi procesoriaus talpa yra maksimaliai padidinta naudojant pridedamame faile pateiktą metodą, aš naudoju „Arduino Uno“kaip valdymo bloką, kuris naudoja „Arduino Due“išorinį pertraukimą, kad perduotų dažnio vertę „Arduino Due“. Be dažnio valdymo, „Arduino Uno“taip pat valdo amplitudę (per skaitmeninį potencialo matuoklį + „OpAmp“) ir įvestį/išvestį-bus daug vietos žaisti.

1 veiksmas: sukurkite sinusų duomenų masyvą

Kadangi skaičiavimas realiuoju laiku reikalauja centrinio procesoriaus, norint pasiekti geresnių rezultatų, reikalingas sinusinis duomenų masyvas

uint32_t sin768 PROGMEM =…. tuo tarpu x = [0: 5375]; y = 127+127*(sin (2*pi/5376/*arba kai kurie # pageidaujami duomenys priklauso nuo reikalavimo*/))

2 veiksmas: lygiagrečios išvesties įgalinimas

Skirtingai nuo Uno, Due turi ribotą nuorodą. Tačiau, norint sukurti 3 fazių sinusines bangas, pagrįstas „Arduino Uno“, visų pirma, našumas nėra įtikinamas dėl mažo MCLK (16 MHz, o „Due“- 84 MHz), antra, ribotas GPIO gali sukurti ne daugiau kaip 2 fazių išvestį ir jums reikia papildomos analoginę grandinę, kad gautų trečiąją fazę (C = -AB).

GPIO įgalinimas dažniausiai buvo pagrįstas bandymu ir bandymu+nėra naudingas SAM3X duomenų lapas

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO valdiklis PIO įjungimo registras (žr. ATMEL SAM3X duomenų lapo p656) ir https://arduino.cc/en/Hacking/PinMappingSAM3X, „Arduino Due“kaiščiai 33-41 ir 44-51 buvo įjungti

PIOC-> PIO_OER = 0xFFFFFFFE; // PIO valdiklio išvesties įgalinimo registras, žr. ATMEL SAM3X duomenų lapo p657 PIOC-> PIO_OSR = 0xFFFFFFFE; // PIO valdiklio išvesties būsenos registras, žr. ATMEL SAM3X duomenų lapo p658

PIOC-> PIO_OWER = 0xFFFFFFFE; // PIO išvesties rašymo įgalinimo registras, žr. ATMEL SAM3X duomenų lapo p670

// PIOA-> PIO_PDR = 0x30000000; // pasirenkamas kaip draudimas, neatrodo, kad jis veikimui veiktų, skaitmeninis kaištis 10 prijungiamas prie PC29 ir PA28, skaitmeninis kištukas 4 prijungiamas prie PC29 ir PA28, čia, kad išjungtumėte PIOA #28 ir 29

3 veiksmas: pertraukimo įgalinimas

Norint maksimaliai padidinti našumą, procesoriaus apkrova turėtų būti kuo mažesnė. Tačiau dėl ne 1–1 atitikimo tarp CPU kaiščio ir „Due“kaiščio būtina atlikti bitų operaciją.

Galite toliau optimizuoti algoritmą, tačiau kambarys yra labai ribotas.

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

t = t%mėginių; // vietoj „if“naudokite t%pavyzdžių, kad išvengtumėte t perpildymo

phaseAInc = (iš anksto nustatytas*t)%5376; // naudokite %5376, kad išvengtumėte masyvo indekso perpildymo

phaseBInc = (fazėAInc+1792)%5376;

phaseCInc = (fazėAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // žr. PIOC: PC1-PC8, atitinkamas „Arduino“kaištis: 33-40 kaištis, todėl perkelkite į kairę 1 skaitmeniui

p_B = sin768 [fazėBInc] << 12; // žr. PIOC: PC12-PC19, atitinkamas „Arduino“kaištis: kaištis 51-44, taigi perėjimas į kairę 12 skaitmenų

p_C = sin768 [fazėCInc]; // C fazės išvestyje naudojamas PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 ir PC29, atitinkamas „Arduino Due“kaištis: skaitmeninis kaištis: atitinkamai 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C & B11000000) << 22; // tai sukuria PC28 ir PC29

p_C3 = (p_C & B00111111) << 21; // tai sukuria PC21-PC26

p_C = p_C2 | p_C3; // tai sukuria lygiagretų C fazės išėjimą

p_A = p_A | p_B | p_C; // 32 bitų išvestis = A fazė (8 bitų) | B fazė | C fazė

PIOC-> PIO_ODSR = p_A; // išvesties registras = p_A

t ++; }

4 žingsnis: R/2R DAC

Sukurkite 3x8bit R/2R DAC, daug informacijos „Google“.

5 žingsnis: visas kodas

#define _BV (x) (1 << (x)); uint32_t sin768 PROGMEM = /* x = [0: 5375]; y = 127+127*(nuodėmė (2*pi/5376))*/

uint32_t p_A, p_B, p_C, p_C2, p_C3; // A fazės B fazės C reikšmė-nors išvestis yra tik 8 bitai, p_A ir p_B reikšmės bus naudojamos, kad būtų sukurta nauja 32 bitų vertė, kad būtų galima susidoroti su 32 bitų PIOC išvestimi

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t intervalas; uint16_t mėginiai, iš anksto nustatyti; uint32_t t = 0;

void setup () {

// lygiagrečios išvesties PIOC sąranka: „Arduino Due“kaiščiai 33-40 naudojami kaip A fazės išėjimas, o 44-51 kaištis veikia B fazės išėjimui

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO valdiklis PIO įjungimo registras (žr. ATMEL SAM3X duomenų lapo p656) ir https://arduino.cc/en/Hacking/PinMappingSAM3X, „Arduino Due“kaiščiai 33-41 ir 44-51 buvo įjungti

PIOC-> PIO_OER = 0xFFFFFFFE; // PIO valdiklio išvesties įgalinimo registras, žr. ATMEL SAM3X duomenų lapo p657

PIOC-> PIO_OSR = 0xFFFFFFFE; // PIO valdiklio išvesties būsenos registras, žr. ATMEL SAM3X duomenų lapo p658

PIOC-> PIO_OWER = 0xFFFFFFFE; // PIO išvesties rašymo įgalinimo registras, žr. ATMEL SAM3X duomenų lapo p670

// PIOA-> PIO_PDR = 0x30000000; // pasirenkamas kaip draudimas, neatrodo, kad jis veiktų, skaitmeninis kaištis 10 prijungiamas prie PC29 ir PA28, skaitmeninis kištukas 4 prijungiamas prie PC29 ir PA28, čia norėdami išjungti PIOA #28 ir 29 // laikmačio sąranką, žr.: //arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (klaidinga); // išjungti maitinimo valdymo valdymo registrų apsaugą nuo rašymo

pmc_enable_periph_clk (ID_TC7); // įjungti periferinio laikrodžio laiko skaitiklį 7

TC_Configure (/ * laikrodis */TC2,/ * kanalas */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // TC laikrodis 42MHz (laikrodis, kanalas, palyginimo režimo nustatymas) TC_SetRC (TC2, 1, intervalas); TC_Start (TC2, 1);

// įjungti laikmačio pertraukimus laikmačiu TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = pertraukimo įgalinimo registras TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = pertraukimo išjungimo registras

NVIC_EnableIRQ (TC7_IRQn); // Įjunkite pertraukimą įdėtame vektoriaus pertraukimo valdiklyje freq = 60; // inicijuoti dažnį kaip 60Hz iš anksto nustatytas = 21; // masyvo indekso padidėjimas 21 pavyzdžiu = 256; // išvesties pavyzdžiai 256/ciklo intervalas = 42000000/(dažnis*pavyzdžiai); // pertraukimų skaičius TC_SetRC (TC2, 1, intervalas); // paleisti TC Serial.begin (9600); // bandymui}

void checkFreq ()

{freqNew = 20000;

jei (freq == freqNew) {} kitaip

{freq = freqNew;

if (dažnis> 20000) {freq = 20000; /*maksimalus dažnis 20kHz*/};

jei (dažnis <1) {dažnis = 1; /*min dažnis 1Hz*/};

jei (dažnis> 999) {iš anksto nustatytas = 384; mėginiai = 14;} // jei dažnis> = 1 kHz, po 14 mėginių kiekvienam ciklui

else if (dažnis> 499) {iš anksto nustatytas = 84; mėginiai = 64;} // 500 <= dažnis99) {iš anksto nustatytas = 42; mėginiai = 128;} // 100 Hz <= dažnis <500 Hz, 128 mėginiai per ciklą

else {iš anksto nustatytas = 21; mėginiai = 256;}; // kai dažnis <100Hz, kiekvienam ciklui 256 mėginiai

intervalas = 42000000/(dažnis*mėginiai); t = 0; TC_SetRC (TC2, 1, intervalas); }}

void loop () {

checkFreq (); vėlavimas (100); }

void TC7_Handler (negalioja)

{TC_GetStatus (TC2, 1);

t = t%mėginių; // naudokite t%pavyzdžių, kad išvengtumėte t phaseAInc = (iš anksto nustatytas*t) perpildymo%5376; // naudokite %5376, kad išvengtumėte masyvo indekso perpildymo

phaseBInc = (fazėAInc+1792)%5376;

phaseCInc = (fazėAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // žr. PIOC: PC1-PC8, atitinkamas „Arduino“kaištis: 33-40 kaištis, todėl perkelkite į kairę 1 skaitmeniui

p_B = sin768 [fazėBInc] << 12; // žr. PIOC: PC12-PC19, atitinkamas „Arduino“kaištis: kaištis 51-44, taigi perėjimas į kairę 12 skaitmenų

p_C = sin768 [fazėCInc]; // C fazės išvestyje naudojamas PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 ir PC29, atitinkamas „Arduino Due“kaištis: skaitmeninis kaištis: atitinkamai 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C & B11000000) << 22; // tai sukuria PC28 ir PC29

p_C3 = (p_C & B00111111) << 21; // tai sukuria PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // tai sukuria lygiagretų C fazės išėjimą

p_A = p_A | p_B | p_C; // 32 bitų išvestis = fazė A (8 bitų) | fazė B | fazė C //Serial.println(p_A>>21, BIN); // PIOC-> PIO_ODSR = 0x37E00000;

PIOC-> PIO_ODSR = p_A; // išvesties registras = p_A t ++; }

Rekomenduojamas: