Съдържание:

Трифазен генератор на синусоидални вълни, базиран на Arduino Due: 5 стъпки
Трифазен генератор на синусоидални вълни, базиран на Arduino Due: 5 стъпки

Видео: Трифазен генератор на синусоидални вълни, базиран на Arduino Due: 5 стъпки

Видео: Трифазен генератор на синусоидални вълни, базиран на Arduino Due: 5 стъпки
Видео: Кто такой Никола Тесла? - Истины, которые должен знать каждый о Николе Тесле 2024, Юли
Anonim
Трифазен генератор на синусоидална вълна, базиран на Arduino Due
Трифазен генератор на синусоидална вълна, базиран на Arduino Due

целта на този споделяне е да помогне на някой, който се опитва да използва по-голямата производителност на Due + липсата на справки + неполезни таблици с данни.

този проект е в състояние да генерира до 3 фази синусоидална вълна @ 256 проби / цикъл при ниски честоти (<1kHz) и 16 проби / цикъл при високи честоти (до 20kHz), което е достатъчно добро, за да бъде изгладено от прости LPF и изходът е почти перфектен.

прикаченият файл не беше последната ми версия, защото добавих допълнителна функция, но ядрото е същото. Обърнете внимание, че пробите/цикълът са зададени по -ниско от горното твърдение.

тъй като капацитетът на процесора е увеличен чрез подхода, показан в прикачения файл, използвах Arduino Uno като контролен блок, който използва външното прекъсване на Arduino Due, за да предаде стойността на честотата към Arduino Due. В допълнение към честотния контрол, Arduino Uno също така контролира амплитудата (чрез цифров потенциометър + OpAmp), както и I/O --- ще има много място за игра.

Стъпка 1: Генерирайте масив от данни за синусоида

Тъй като изчислението в реално време изисква CPU, за по-добра производителност е необходим масив от синусоидални данни

uint32_t sin768 ПРОГМЕТА = …. докато x = [0: 5375]; y = 127+127*(грех (2*pi/5376/*или някои #, които предпочитате, зависи от изискването*/))

Стъпка 2: Активиране на паралелен изход

За разлика от Uno, Due имат ограничени препратки. Въпреки това, за да се генерира 3 -фазова синусоида, базирана на Arduino Uno, първо, производителността не се аплодира поради ниската му MCLK (16MHz, докато Due е 84MHz), второ, това е ограничено GPIO може да произведе максимум 2 фазов изход и имате нужда от допълнителен аналогова верига за производство на 3-та фаза (C = -AB).

След активирането на GPIO се основаваше предимно на опити и проби+неполезни таблици с данни на SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO контролер Регистърът за активиране на PIO (вижте стр. 656 на листа с данни на ATMEL SAM3X) и https://arduino.cc/en/Hacking/PinMappingSAM3X, пин 33-41 и 44-51 на Arduino Due са активирани

PIOC-> PIO_OER = 0xFFFFFFFE; // Регистър за разрешаване на изхода на PIO контролер, вижте стр. 657 на листа с данни ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // Регистър на състоянието на изхода на PIO контролер, вижте стр. 658 от листа с данни ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Регистър за разрешаване на запис на изход PIO, вижте p670 на листа с данни ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // по избор като застраховка, изглежда не влияе на производителността, цифров щифт 10 се свързва както с PC29, така и с PA28, цифров щифт 4 се свързва както с PC29, така и с PA28, тук за деактивиране на PIOA #28 & 29

Стъпка 3: Активиране на прекъсване

За да се постигне максимална производителност, натоварването на процесора трябва да бъде възможно най -ниско. Въпреки това, поради не-1to1 съответствие между пина на процесора и дължимия пин, операцията с битове е необходима.

Можете допълнително да оптимизирате алгоритъма, но мястото е много ограничено.

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

t = t%проби; // използваме t%проби вместо „if“, за да избегнем препълване на t

phaseAInc = (предварително зададено*t)%5376; // използвайте %5376, за да избегнете препълване на индекса на масива

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // вижте PIOC: PC1 до PC8, съответстващ щифт Arduino Due: щифт 33-40, следователно изместване наляво за 1 цифра

p_B = sin768 [phaseBInc] << 12; // вижте PIOC: PC12 към PC19, съответстващ щифт Arduino Due: щифт 51-44, следователно изместване наляво 12 цифри

p_C = sin768 [phaseCInc]; // фаза C изход служител PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 и PC29, съответстващ щифт Arduino Due: цифров пин: съответно 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C & B11000000) << 22; // това генерира PC28 и PC29

p_C3 = (p_C & B00111111) << 21; // това генерира PC21-PC26

p_C = p_C2 | p_C3; // това генерира паралелен изход на фаза C

p_A = p_A | p_B | p_C; // 32 битов изход = фаза A (8 бита) | фаза B | фаза C

PIOC-> PIO_ODSR = p_A; // изходен регистър = p_A

t ++; }

Стъпка 4: R/2R DAC

изградете 3x8bit R/2R DAC, много реф в google.

Стъпка 5: Пълен код

#define _BV (x) (1 << (x)); uint32_t sin768 ПРОГМЕТА = /* x = [0: 5375]; y = 127+127*(грех (2*pi/5376))*/

uint32_t p_A, p_B, p_C, p_C2, p_C3; // фаза A фаза B стойност на фаза C-макар че изходът е само 8 бита, стойностите p_A и p_B ще се управляват, за да се генерира нова 32-битова стойност, за да се копира с 32-битов PIOC изход

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t интервал; uint16_t проби, предварително зададени; uint32_t t = 0;

void setup () {

// настройка на паралелен изход PIOC: Arduino Due щит 33-40 се използва като изход фаза А, докато щифт 44-51 работи за изход фаза В

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO контролер Регистърът за активиране на PIO (вижте стр. 656 на листа с данни на ATMEL SAM3X) и https://arduino.cc/en/Hacking/PinMappingSAM3X, пин 33-41 и 44-51 на Arduino Due са активирани

PIOC-> PIO_OER = 0xFFFFFFFE; // Регистър за разрешаване на изхода на PIO контролер, вижте стр. 657 от листа с данни ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // Регистър на състоянието на изхода на PIO контролер, вижте стр. 658 от листа с данни ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Регистър за разрешаване на запис на изход PIO, вижте p670 на листа с данни ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // по избор като застраховка, изглежда не влияе на производителността, цифров щифт 10 се свързва както към PC29, така и към PA28, цифров щифт 4 се свързва както към PC29, така и към PA28, тук, за да деактивирате деактивирането на PIOA #28 & 29 // настройка на таймера, вижте https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (невярно); // деактивира защитата срещу запис на регистрите за управление на захранването

pmc_enable_periph_clk (ID_TC7); // активирайте брояча на периферния часовник 7

TC_Configure (/ * часовник */TC2,/ * канал */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // TC часовник 42MHz (часовник, канал, настройка на режим за сравнение) TC_SetRC (TC2, 1, интервал); TC_Start (TC2, 1);

// разрешаване на прекъсвания на таймера на таймера TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = регистър за разрешаване на прекъсване TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = регистър за деактивиране на прекъсване

NVIC_EnableIRQ (TC7_IRQn); // Активиране на прекъсването във вмъкнатия контролер за прекъсване на вектор freq = 60; // инициализираме честотата като 60Hz предварително зададена = 21; // увеличение на индекса на масива с 21 проби = 256; // изходни проби 256/интервал на цикъл = 42000000/(честотни*проби); // преброяване на прекъсвания TC_SetRC (TC2, 1, интервал); // стартиране на TC Serial.begin (9600); // за целите на теста}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} иначе

{freq = freqNew;

ако (честота> 20000) {честота = 20000; /*максимална честота 20kHz*/};

ако (честота <1) {честота = 1; /*мин. честота 1Hz*/};

if (freq> 999) {preset = 384; проби = 14;} // за честота> = 1kHz, 14 проби за всеки цикъл

else if (freq> 499) {preset = 84; проби = 64;} // за 500 <= честота99) {предварително зададена = 42; проби = 128;} // за 100Hz <= честота <500Hz, 128 проби/цикъл

else {preset = 21; проби = 256;}; // за честота <100hz, 256 проби за всеки цикъл

интервал = 42000000/(честотни*проби); t = 0; TC_SetRC (TC2, 1, интервал); }}

void loop () {

checkFreq (); забавяне (100); }

void TC7_Handler (void)

{TC_GetStatus (TC2, 1);

t = t%проби; // използваме t%проби, за да избегнем препълването на t phaseAInc = (предварително зададено*t)%5376; // използвайте %5376, за да избегнете препълване на индекса на масива

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // вижте PIOC: PC1 до PC8, съответстващ щифт Arduino Due: щифт 33-40, следователно изместване наляво за 1 цифра

p_B = sin768 [phaseBInc] << 12; // вижте PIOC: PC12 към PC19, съответстващ щифт Arduino Due: щифт 51-44, следователно изместване наляво 12 цифри

p_C = sin768 [phaseCInc]; // фаза C изход служител PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 и PC29, съответстващ щифт Arduino Due: цифров пин: съответно 9, 8, 7, 6, 5, 4, 3, 10

p_C2 = (p_C & B11000000) << 22; // това генерира PC28 и PC29

p_C3 = (p_C & B00111111) << 21; // това генерира PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // това генерира паралелен изход на фаза C

p_A = p_A | p_B | p_C; // 32 битов изход = фаза A (8 бита) | фаза B | фаза C //Serial.println(p_A>> 21, BIN); // PIOC-> PIO_ODSR = 0x37E00000;

PIOC-> PIO_ODSR = p_A; // изходен регистър = p_A t ++; }

Препоръчано: