Tabla de contenido:

Generador de onda sinusoidal trifásica basado en Arduino Due: 5 pasos
Generador de onda sinusoidal trifásica basado en Arduino Due: 5 pasos

Video: Generador de onda sinusoidal trifásica basado en Arduino Due: 5 pasos

Video: Generador de onda sinusoidal trifásica basado en Arduino Due: 5 pasos
Video: TIMER 1 modo PWM 🔥 frecuencia 2, 5 y 10 KHz 💥 ARDUINO con Registros ATMega328P - tiempo MUERTO 2024, Mes de julio
Anonim
Generador de onda sinusoidal trifásica basado en Arduino Due
Generador de onda sinusoidal trifásica basado en Arduino Due

el propósito de este recurso compartido es ayudar a alguien que está tratando de utilizar el mayor rendimiento de Due + falta de referencia + hoja de datos no útil.

Este proyecto es capaz de generar hasta una onda sinusoidal trifásica a 256 muestras / ciclo a baja frecuencia (<1kHz) y 16 muestras / ciclo a alta frecuencia (hasta 20kHz), lo cual es lo suficientemente bueno para ser suavizado por LPF simples y el la salida es casi perfecta.

el archivo adjunto no era mi versión final porque agregué alguna característica adicional, pero el núcleo es el mismo. Tenga en cuenta que las muestras / ciclo se establecieron por debajo de la declaración anterior.

Dado que la capacidad de la CPU se maximiza a través del enfoque que se muestra en el archivo adjunto, utilicé un Arduino Uno como unidad de control, que utiliza la interrupción externa de Arduino Due para pasar el valor de frecuencia a Arduino Due. Además del control de frecuencia, el Arduino Uno también controla la amplitud (a través del medidor de potencial digital + OpAmp) así como la E / S; habrá mucho espacio para jugar.

Paso 1: generar una matriz de datos sinusoidal

Dado que el cálculo en tiempo real es exigente para la CPU, se requiere una matriz de datos sinusoidal para un mejor rendimiento

uint32_t sin768 PROGMEM =….mientras que x = [0: 5375]; y = 127 + 127 * (sin (2 * pi / 5376 / * o algún # que prefiera depende del requisito * /))

Paso 2: Habilitación de la salida en paralelo

A diferencia de Uno, Due tienen una referencia limitada. Sin embargo, para generar una onda sinusoidal trifásica basada en Arduino Uno, en primer lugar, el rendimiento no es aceptable debido a su bajo MCLK (16MHz mientras que Due es 84MHz), segundo, su GPIO limitado puede producir una salida máxima de 2 fases y necesita más circuito analógico para producir la 3ª fase (C = -AB).

La siguiente habilitación de GPIO se basó principalmente en prueba y prueba + hoja de datos no útil de SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // Controlador PIO PIO Enable register (consulte la p656 de la hoja de datos ATMEL SAM3X) y https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 y 44-51 fueron habilitados

PIOC-> PIO_OER = 0xFFFFFFFE; // Registro de habilitación de salida del controlador PIO, consulte la p657 de la hoja de datos ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // Registro de estado de salida del controlador PIO, consulte la p658 de la hoja de datos ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registro de habilitación de escritura de salida PIO, consulte la p670 de la hoja de datos ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // opcional como seguro, no parece afectar el rendimiento, el pin digital 10 se conecta a PC29 y PA28, el pin digital 4 se conecta a PC29 y PA28, aquí para deshabilitar deshabilitar PIOA # 28 y 29

Paso 3: Habilitación de la interrupción

Para maximizar su rendimiento, la carga de la CPU debe ser lo más baja posible. Sin embargo, debido a la correspondencia no 1 a 1 entre el pin de la CPU y el pin Due, la operación de bits es necesaria.

Puede optimizar aún más el algoritmo, pero el espacio es muy limitado.

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

t = t% de muestras; // use t% samples en lugar de 'if' para evitar el desbordamiento de t

PhaseAInc = (preestablecido * t)% 5376; // use% 5376 para evitar el desbordamiento del índice de la matriz

faseBInc = (faseAInc + 1792)% 5376;

faseCInc = (faseAInc + 3584)% 5376;

p_A = sin768 [phaseAInc] << 1; // consulte PIOC: PC1 a PC8, pin correspondiente de Arduino Due: pin 33-40, por lo tanto, cambie a la izquierda para 1 dígito

p_B = sin768 [faseBInc] << 12; // consulte PIOC: PC12 a PC19, pin correspondiente de Arduino Due: pin 51-44, por lo tanto, cambie a la izquierda 12 dígitos

p_C = sin768 [phaseCInc]; // empleo de salida de fase C PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 y PC29, correspondiente pin Arduino Due: pin digital: 9, 8, 7, 6, 5, 4, 3, 10, respectivamente

p_C2 = (p_C & B11000000) << 22; // esto genera PC28 y PC29

p_C3 = (p_C & B00111111) << 21; // esto genera PC21-PC26

p_C = p_C2 | p_C3; // esto genera una salida en paralelo de la fase C

p_A = p_A | p_B | p_C; // Salida de 32 bits = fase A (8 bits) | fase B | fase C

PIOC-> PIO_ODSR = p_A; // registro de salida = p_A

t ++; }

Paso 4: R / 2R DAC

construya 3x8bit R / 2R DAC, un montón de referencias en google.

Paso 5: Código completo

#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; // fase A fase B valor de fase C - aunque las salidas son solo de 8 bits, los valores p_A y p_B se operarán para generar un nuevo valor de 32 bits con el fin de copiar con la salida PIOC de 32 bits

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; intervalo uint32_t; uint16_t samples, preset; uint32_t t = 0;

configuración vacía () {

// Configuración de PIOC de salida paralela: los pines 33-40 de Arduino Due se emplean como salida de fase A mientras que el pin 44-51 funciona para la salida de fase B

PIOC-> PIO_PER = 0xFFFFFFFE; // Controlador PIO PIO Enable register (consulte la p656 de la hoja de datos ATMEL SAM3X) y https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 y 44-51 fueron habilitados

PIOC-> PIO_OER = 0xFFFFFFFE; // Registro de habilitación de salida del controlador PIO, consulte la p657 de la hoja de datos ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // Registro de estado de salida del controlador PIO, consulte la p658 de la hoja de datos ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registro de habilitación de escritura de salida PIO, consulte la p670 de la hoja de datos de ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // opcional como seguro, no parece afectar el rendimiento, el pin digital 10 se conecta a PC29 y PA28, el pin digital 4 se conecta a PC29 y PA28, aquí para deshabilitar deshabilitar PIOA # 28 y 29 // configuración del temporizador, consulte https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (falso); // deshabilitar la protección contra escritura de los registros de control de administración de energía

pmc_enable_periph_clk (ID_TC7); // habilitar el contador de tiempo del reloj periférico 7

TC_Configure (/ * reloj * / TC2, / * canal * / 1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // Reloj TC 42MHz (reloj, canal, ajuste de modo de comparación) TC_SetRC (TC2, 1, intervalo); TC_Start (TC2, 1);

// habilita las interrupciones del temporizador en el temporizador TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = registro de habilitación de interrupciones TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = registro de desactivación de interrupciones

NVIC_EnableIRQ (TC7_IRQn); // Habilita la interrupción en el controlador de interrupciones vectoriales anidado freq = 60; // inicializar la frecuencia como preajuste de 60Hz = 21; // aumento del índice de la matriz en 21 muestras = 256; // muestras de salida 256 / intervalo de ciclo = 42000000 / (frecuencia * muestras); // interrupción cuenta TC_SetRC (TC2, 1, intervalo); // iniciar TC Serial.begin (9600); // con fines de prueba}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} más

{freq = freqNew;

si (frecuencia> 20000) {frecuencia = 20000; / * frecuencia máxima 20 kHz * /};

si (frecuencia <1) {frecuencia = 1; / * frecuencia mínima 1Hz * /};

if (freq> 999) {preset = 384; samples = 14;} // para frecuencia> = 1kHz, 14 muestras para cada ciclo

else if (freq> 499) {preset = 84; samples = 64;} // para 500 <= frecuencia99) {preset = 42; samples = 128;} // para 100Hz <= frecuencia <500Hz, 128 muestras / ciclo

else {preset = 21; muestras = 256;}; // para frecuencia <100 hz, 256 muestras para cada ciclo

intervalo = 42000000 / (frecuencia * muestras); t = 0; TC_SetRC (TC2, 1, intervalo); }}

bucle vacío () {

checkFreq (); retraso (100); }

vacío TC7_Handler (vacío)

{TC_GetStatus (TC2, 1);

t = t% de muestras; // use t% samples para evitar el desbordamiento de t phaseAInc = (preset * t)% 5376; // use% 5376 para evitar el desbordamiento del índice de la matriz

faseBInc = (faseAInc + 1792)% 5376;

faseCInc = (faseAInc + 3584)% 5376;

p_A = sin768 [phaseAInc] << 1; // consulte PIOC: PC1 a PC8, pin correspondiente de Arduino Due: pin 33-40, por lo tanto, cambie a la izquierda para 1 dígito

p_B = sin768 [faseBInc] << 12; // consulte PIOC: PC12 a PC19, pin correspondiente de Arduino Due: pin 51-44, por lo tanto, mueva 12 dígitos a la izquierda

p_C = sin768 [phaseCInc]; // empleo de salida de fase C PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 y PC29, correspondiente pin Arduino Due: pin digital: 9, 8, 7, 6, 5, 4, 3, 10, respectivamente

p_C2 = (p_C & B11000000) << 22; // esto genera PC28 y PC29

p_C3 = (p_C & B00111111) << 21; // esto genera PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // esto genera una salida en paralelo de la fase C

p_A = p_A | p_B | p_C; // Salida de 32 bits = fase A (8 bits) | fase B | fase C //Serial.println(p_A>>21, BIN); // PIOC-> PIO_ODSR = 0x37E00000;

PIOC-> PIO_ODSR = p_A; // registro de salida = p_A t ++; }

Recomendado: