Spisu treści:

3-fazowy generator fal sinusoidalnych oparty na Arduino Due: 5 kroków
3-fazowy generator fal sinusoidalnych oparty na Arduino Due: 5 kroków

Wideo: 3-fazowy generator fal sinusoidalnych oparty na Arduino Due: 5 kroków

Wideo: 3-fazowy generator fal sinusoidalnych oparty na Arduino Due: 5 kroków
Wideo: Вебинар Фесто Электротехника май 2020 г. 2024, Lipiec
Anonim
3-fazowy generator fal sinusoidalnych oparty na Arduino Due
3-fazowy generator fal sinusoidalnych oparty na Arduino Due

celem tego udostępnienia jest pomoc komuś, kto próbuje wykorzystać większą wydajność Due + brak odniesienia + nieprzydatny arkusz danych.

ten projekt jest w stanie wygenerować do 3 faz sinusoidy przy 256 próbkach/cykl przy niskich częstotliwościach (<1kHz) i 16 próbkach/cykl przy wysokich częstotliwościach (do 20kHz), co jest wystarczająco dobre, aby być wygładzone przez proste filtry LPF i wydajność jest prawie idealna.

załączony plik nie był moją ostateczną wersją, ponieważ dodałem kilka dodatkowych funkcji, ale rdzeń jest taki sam. Zwróć uwagę, że próbki/cykl zostały ustawione na niższym poziomie niż w powyższym oświadczeniu.

ponieważ wydajność procesora jest maksymalizowana dzięki podejściu pokazanemu w załączonym pliku, użyłem Arduino Uno jako jednostki sterującej, która wykorzystuje zewnętrzne przerwanie Arduino Due do przekazywania wartości częstotliwości do Arduino Due. Oprócz kontroli częstotliwości, Arduino Uno kontroluje również amplitudę (poprzez cyfrowy miernik potencjału + OpAmp) oraz I/O – będzie dużo miejsca do zabawy.

Krok 1: Wygeneruj sinusoidalną tablicę danych

Ponieważ obliczenia w czasie rzeczywistym wymagają dużej mocy obliczeniowej procesora, do uzyskania lepszej wydajności wymagana jest macierz danych sinusoidalnych

uint32_t sin768 PROGMEM= ….gdy x=[0:5375]; y = 127+127*(sin(2*pi/5376/*lub niektóre #, które wolisz, zależy od wymagań*/))

Krok 2: Włączanie wyjścia równoległego

W przeciwieństwie do Uno, Due mają ograniczone odniesienie. Jednak, aby wygenerować 3-fazową falę sinusoidalną w oparciu o Arduino Uno, po pierwsze, wydajność nie jest zadowalająca ze względu na niski MCLK (16 MHz, podczas gdy Due to 84 MHz), po drugie, jest ograniczone GPIO może wytworzyć maksymalnie 2 fazowe wyjście i potrzebujesz dodatkowych obwód analogowy do wytwarzania trzeciej fazy (C=-AB).

Po włączeniu GPIO opierało się głównie na próbie i nieprzydatnym arkuszu danych SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; //PIO controller PIO Enable register (patrz p656 arkusza danych ATMEL SAM3X) i https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 i 44-51 zostały włączone

PIOC->PIO_OER = 0xFFFFFFFE; //Rejestr aktywacji wyjść kontrolera PIO, patrz p657 karty katalogowej ATMEL SAM3X PIOC->PIO_OSR = 0xFFFFFFFE; //Rejestr stanu wyjść kontrolera PIO, patrz p658 karty katalogowej ATMEL SAM3X

PIOC->PIO_MOC = 0xFFFFFFFE; //rejestr umożliwiający zapis wyjścia PIO, patrz p670 arkusza danych ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //opcjonalne jako ubezpieczenie, nie wydaje się wpływać na wydajność, cyfrowy pin 10 łączy się z PC29 i PA28, cyfrowy pin 4 łączy się z PC29 i PA28, tutaj, aby wyłączyć PIOA #28 i 29

Krok 3: Włączanie przerwania

Aby zmaksymalizować jego wydajność, obciążenie procesora powinno być jak najmniejsze. Jednak ze względu na niezgodność między pinem procesora a pinem Due, konieczna jest operacja bitowa.

Możesz jeszcze bardziej zoptymalizować algorytm, ale pomieszczenie jest bardzo ograniczone.

nieważny TC7_Handler(void){ TC_GetStatus(TC2, 1);

t = t%próbek; //użyj t%samples zamiast 'if', aby uniknąć przepełnienia t

phaseAInc = (ustawienie wstępne*t)%5376; //użyj %5376, aby uniknąć przepełnienia indeksu tablicy

fazaBInc = (fazaAInc+1792)%5376;

faza CInc = (faza AInc+3584)%5376;

p_A = sin768[fazaAInc]<<1; //odnieś się do PIOC: PC1 do PC8, odpowiadający pin Arduino Due: pin 33-40, stąd przesunięcie w lewo o 1 cyfrę

p_B = sin768[phaseBInc]<<12; //odsyłamy do PIOC: PC12 do PC19, odpowiedni pin Arduino Due: pin 51-44, stąd przesunięcie w lewo o 12 cyfr

p_C = sin768[phaseCInc]; //wyjście fazy C wykorzystuje PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 i PC29, odpowiedni pin Arduino Due: pin cyfrowy: odpowiednio 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C&B11000000)<<22; //to generuje PC28 i PC29

p_C3 = (p_C&B00111111)<<21; //to generuje PC21-PC26

p_C = p_C2|p_C3; //to generuje równoległe wyjście fazy C

p_A = p_A|p_B|p_C; //32-bitowe wyjście = faza A (8bit)|faza B|faza C

PIOC->PIO_ODSR = p_A; //rejestr wyjściowy =p_A

t++; }

Krok 4: DAC R/2R

zbuduj 3x8bit R/2R DAC, mnóstwo ref w google.

Krok 5: Pełny 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, wartość fazy C--chociaż dane wyjściowe są tylko 8-bitowe, wartości p_A i p_B będą używane w celu wygenerowania nowej wartości 32-bitowej w celu skopiowania z 32-bitowym wyjściem PIOC

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; interwał uint32_t; próbki uint16_t, wstępnie ustawione; uint32_t = 0;

pusta konfiguracja () {

//konfiguracja PIOC wyjścia równoległego: Arduino Due pin33-40 jest używany jako wyjście fazy A, podczas gdy pin 44-51 działa jako wyjście fazy B

PIOC->PIO_PER = 0xFFFFFFFE; //PIO controller PIO Enable register (patrz p656 arkusza danych ATMEL SAM3X) i https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 i 44-51 zostały włączone

PIOC->PIO_OER = 0xFFFFFFFE; //Rejestr aktywacji wyjścia kontrolera PIO, patrz p657 arkusza danych ATMEL SAM3X

PIOC->PIO_OSR = 0xFFFFFFFE; //Rejestr stanu wyjść kontrolera PIO, patrz p658 karty katalogowej ATMEL SAM3X

PIOC->PIO_MOC = 0xFFFFFFFE; //rejestr umożliwiający zapis wyjścia PIO, patrz p670 arkusza danych ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //opcjonalne jako ubezpieczenie, nie wydaje się wpływać na wydajność, cyfrowy pin 10 łączy się z PC29 i PA28, cyfrowy pin 4 łączy się z PC29 i PA28, tutaj, aby wyłączyć konfigurację PIOA #28 i 29 //timer, patrz https://arduino.cc/pl/Hacking/PinMappingSAM3X, pmc_set_writeprotect(fałsz); // wyłącz ochronę przed zapisem rejestrów Power Management Control

pmc_enable_periph_clk(ID_TC7); // włącz licznik czasu zegara peryferyjnego 7

TC_Configure(/* zegar */TC2, /* kanał */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //TC clock 42MHz (zegar, kanał, ustawienie trybu porównania) TC_SetRC(TC2, 1, interwał); TC_Start(TC2, 1);

// włącz przerwania zegara na zegarze TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = przerwanie włącza rejestr TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = przerwanie rejestru wyłączającego

NVIC_EnableIRQ(TC7_IRQn); // Włącz przerwanie w zagnieżdżonym wektorowym kontrolerze przerwań freq = 60; //zainicjuj częstotliwość jako wstępnie ustawione 60Hz = 21; //wzrost indeksu tablicy o 21 próbek = 256; //próbki wyjściowe 256/okres cyklu = 42000000/(częstot*próbki); //liczba przerwań TC_SetRC(TC2, 1, interwał); //uruchom TC Serial.begin(9600); //do celów testowych }

nieważna częstotliwość sprawdzania()

{ częst. Nowy = 20000;

if (freq == freqNew) {} else

{ częst = częstNowy;

jeśli (częst>20000) {częst = 20000; /*maksymalna częstotliwość 20kHz*/};

jeśli (częst.<1) {częst. = 1; /*min częstotliwość 1Hz*/};

if (częst>999) {nastawa = 384; sample = 14;} //dla częstotliwości >=1kHz, 14 próbek na każdy cykl

else if (częst>499) {nastawa = 84; sample = 64;} //dla 500<=częstotliwość99) {preset = 42; próbki = 128;} //dla 100Hz<=częstotliwość<500Hz, 128 próbek/cykl

inaczej {ustawienie wstępne = 21; próbki = 256;}; //dla częstotliwości <100hz, 256 próbek na każdy cykl

interwał = 42000000/(częst.*próbki); t = 0; TC_SetRC(TC2, 1, interwał); } }

pusta pętla () {

checkFreq(); opóźnienie (100); }

nieważne TC7_Handler(unieważnione)

{ TC_PobierzStatus(TC2, 1);

t = t%próbek; //użyj t%samples, aby uniknąć przepełnienia t phaseAInc = (preset*t)%5376; //użyj %5376, aby uniknąć przepełnienia indeksu tablicy

fazaBInc = (faza AInc+1792)%5376;

faza CInc = (faza AInc+3584)%5376;

p_A = sin768[fazaAInc]<<1; //odnieś się do PIOC: PC1 do PC8, odpowiadający pin Arduino Due: pin 33-40, stąd przesunięcie w lewo o 1 cyfrę

p_B = sin768[phaseBInc]<<12; //patrz PIOC: PC12 do PC19, odpowiedni pin Arduino Due: pin 51-44, stąd przesunięcie w lewo o 12 cyfr

p_C = sin768[phaseCInc]; //wyjście fazy C wykorzystuje PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 i PC29, odpowiedni pin Arduino Due: pin cyfrowy: odpowiednio 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C&B11000000)<<22; //to generuje PC28 i PC29

p_C3 = (p_C&B00111111)<<21; //to generuje PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2|p_C3; //to generuje równoległe wyjście fazy C

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

PIOC->PIO_ODSR = p_A; //rejestr wyjściowy =p_A t++; }

Zalecana: