Оглавление:

Генератор 3-фазной синусоидальной волны на базе Arduino Due: 5 шагов
Генератор 3-фазной синусоидальной волны на базе Arduino Due: 5 шагов

Видео: Генератор 3-фазной синусоидальной волны на базе Arduino Due: 5 шагов

Видео: Генератор 3-фазной синусоидальной волны на базе Arduino Due: 5 шагов
Видео: Самый простой генератор сигналов для лаборатории радиолюбителя от 1Гц до 2МГц 2024, Июль
Anonim
Генератор 3-фазной синусоидальной волны на базе Arduino Due
Генератор 3-фазной синусоидальной волны на базе Arduino Due

цель этой публикации - помочь тем, кто пытается использовать более высокую производительность Due + отсутствие справочной информации + бесполезную таблицу данных.

этот проект способен генерировать до 3-х фазных синусоидальных волн при 256 отсчетов / цикл на низкой частоте (<1 кГц) и 16 отсчетов / цикл при высокой частоте (до 20 кГц), что достаточно хорошо для сглаживания простыми LPF и вывод почти идеальный.

прикрепленный файл не был моей последней версией, потому что я добавил некоторые дополнительные функции, но ядро такое же. Обратите внимание, что выборка / цикл была установлена ниже, чем указано выше.

поскольку емкость ЦП максимизируется с помощью подхода, показанного в прикрепленном файле, я использовал Arduino Uno в качестве блока управления, который использует внешнее прерывание Arduino Due для передачи значения частоты в Arduino Due. В дополнение к контролю частоты, Arduino Uno также контролирует амплитуду (через цифровой измеритель потенциала + операционный усилитель), а также ввод / вывод - будет много места для игры.

Шаг 1: Создайте массив данных синусоиды

Поскольку расчет в реальном времени требует ресурсов ЦП, для повышения производительности требуется массив синусоидальных данных.

uint32_t sin768 PROGMEM =…. while x = [0: 5375]; y = 127 + 127 * (sin (2 * pi / 5376 / * или какой-то другой #, который вы предпочитаете, зависит от требований * /))

Шаг 2: Включение параллельного вывода

В отличие от Uno, у Due есть ограниченное количество ссылок. Однако для генерации 3-фазной синусоидальной волны на основе Arduino Uno, во-первых, производительность неприемлема из-за его низкого MCLK (16 МГц, а Due - 84 МГц), во-вторых, ограниченный GPIO может выдавать максимум 2-фазный выход, и вам нужны дополнительные аналоговая схема для получения 3-й фазы (C = -AB).

Последующее включение GPIO было в основном основано на пробной версии + не полезное техническое описание SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // Регистр включения PIO контроллера PIO (см. P656 таблицы данных ATMEL SAM3X) и https://arduino.cc/en/Hacking/PinMappingSAM3X, были включены выводы 33-41 и 44-51 Arduino Due

PIOC-> PIO_OER = 0xFFFFFFFE; // Регистр разрешения выхода контроллера PIO, см. P657 таблицы данных ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // Регистр состояния выхода контроллера PIO, см. P658 таблицы данных ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Регистр разрешения записи выхода PIO, см. P670 таблицы данных ATMEL SAM3X

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

Шаг 3: Включение прерывания

Чтобы обеспечить максимальную производительность, загрузка процессора должна быть как можно ниже. Однако из-за соответствия не 1: 1 между выводом CPU и выводом Due, необходима битовая операция.

Вы можете дополнительно оптимизировать алгоритм, но комната очень ограничена.

недействительным TC7_Handler (недействительным) {TC_GetStatus (TC2, 1);

t = t% образцов; // используйте t% samples вместо 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

построить 3x8bit R / 2R DAC, множество ссылок в Google.

Шаг 5: Полный код

#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; // фаза A фаза B значение фазы C - хотя выход только 8-битный, значения p_A и p_B будут использоваться для генерации нового 32-битного значения для копирования с 32-битным выходом PIOC

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

void setup () {

// Параллельный выход Настройка PIOC: контакты 33-40 Arduino Due используются как выход фазы A, а контакты 44-51 работают как выход фазы B

PIOC-> PIO_PER = 0xFFFFFFFE; // Регистр включения PIO контроллера PIO (см. P656 таблицы данных ATMEL SAM3X) и https://arduino.cc/en/Hacking/PinMappingSAM3X, были включены выводы 33-41 и 44-51 Arduino Due

PIOC-> PIO_OER = 0xFFFFFFFE; // Регистр разрешения выхода контроллера PIO, см. P657 таблицы данных ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // Регистр состояния выхода контроллера PIO, см. P658 таблицы данных 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 clock 42MHz (часы, канал, настройка режима сравнения) TC_SetRC (TC2, 1, interval); 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; // инициализируем частоту как 60 Гц preset = 21; // увеличение индекса массива на 21 выборку = 256; // вывод сэмплов 256 / интервал цикла = 42000000 / (freq * samples); // количество прерываний TC_SetRC (TC2, 1, interval); // запускаем TC Serial.begin (9600); // в тестовых целях}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} еще

{freq = freqNew;

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

если (частота <1) {частота = 1; / * минимальная частота 1 Гц * /};

если (частота> 999) {preset = 384; samples = 14;} // для частоты> = 1 кГц, 14 выборок на каждый цикл

иначе, если (частота> 499) {preset = 84; samples = 64;} // для 500 <= frequency99) {preset = 42; samples = 128;} // для 100 Гц <= частота <500 Гц 128 выборок / цикл

иначе {preset = 21; образцы = 256;}; // для частоты <100 Гц, 256 отсчетов для каждого цикла

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

void loop () {

checkFreq (); задержка (100); }

недействительным TC7_Handler (недействительным)

{TC_GetStatus (TC2, 1);

t = t% образцов; // используйте t% образцов, чтобы избежать переполнения t phaseAInc = (preset * 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 ++; }

Рекомендуемые: