Índice:

Gerador de onda senoidal trifásico baseado no Arduino Prazo: 5 etapas
Gerador de onda senoidal trifásico baseado no Arduino Prazo: 5 etapas

Vídeo: Gerador de onda senoidal trifásico baseado no Arduino Prazo: 5 etapas

Vídeo: Gerador de onda senoidal trifásico baseado no Arduino Prazo: 5 etapas
Vídeo: Como gerar um sinal PWM com ARDUINO 2024, Novembro
Anonim
Gerador de onda senoidal trifásico baseado no Arduino Due
Gerador de onda senoidal trifásico baseado no Arduino Due

o objetivo deste compartilhamento é ajudar alguém que está tentando utilizar o melhor desempenho do Due + falta de referência + folha de dados não útil.

este projeto é capaz de gerar até onda senoidal trifásica @ 256 amostras / ciclo em baixa frequência (<1kHz) e 16 amostras / ciclo @ alta frequência (até 20kHz), o que é bom o suficiente para ser suavizado por LPFs simples e o a saída é quase perfeita.

o arquivo anexado não era minha versão final, pois adicionei alguns recursos adicionais, mas o núcleo é o mesmo. Observe que as amostras / ciclo foram definidas abaixo da declaração acima.

como a capacidade da CPU é maximizada por meio da abordagem mostrada no arquivo anexado, usei um Arduino Uno como unidade de controle, que utiliza a interrupção externa do Arduino Due para passar o valor da frequência para o Arduino Due. Além do controle de frequência, o Arduino Uno também controla a amplitude (por meio do medidor de potencial digital + OpAmp), bem como I / O --- haverá muito espaço para brincar.

Etapa 1: Gerar matriz de dados senoidal

Uma vez que o cálculo em tempo real exige muito da CPU, uma matriz de dados senoidal é necessária para um melhor desempenho

uint32_t sin768 PROGMEM =….enquanto x = [0: 5375]; y = 127 + 127 * (sin (2 * pi / 5376 / * ou algum # que você preferir depende do requisito * /))

Etapa 2: Habilitando a saída paralela

Ao contrário de Uno, Due tem referência limitada. No entanto, a fim de gerar onda senoidal trifásica com base no Arduino Uno, primeiro de tudo, o desempenho não é aplicável devido ao seu baixo MCLK (16 MHz enquanto o vencimento é de 84 MHz), segundo, seu GPIO limitado pode produzir saída máxima de 2 fases e você precisa de mais circuito analógico para produzir a 3ª fase (C = -AB).

A ativação do GPIO seguinte baseou-se principalmente na tentativa e teste + folha de dados não útil de SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO controlador PIO Enable register (consulte a p656 da folha de dados ATMEL SAM3X) e https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pino 33-41 e 44-51 foram habilitados

PIOC-> PIO_OER = 0xFFFFFFFE; // Registro de habilitação de saída do controlador PIO, consulte a p657 da folha de dados ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // Registro de status de saída do controlador PIO, consulte a p658 da folha de dados ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registro de habilitação de gravação de saída PIO, consulte a p670 da folha de dados ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // opcional como seguro, não parece afetar o desempenho, o pino digital 10 conecta-se ao PC29 e ao PA28, o pino digital 4 conecta-se ao PC29 e ao PA28, aqui para desativar desabilitar PIOA # 28 e 29

Etapa 3: Habilitando a interrupção

Para maximizar seu desempenho, a carga da CPU deve ser a mais baixa possível. No entanto, devido à correspondência não 1to1 entre o pino da CPU e o pino Devido, a operação do bit é necessária.

Você pode otimizar ainda mais o algoritmo, mas a sala é muito limitada.

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

t = t% amostras; // use t% samples em vez de 'if' para evitar o estouro de t

phaseAInc = (predefinição * t)% 5376; // use% 5376 para evitar estouro de índice de array

phaseBInc = (phaseAInc + 1792)% 5376;

phaseCInc = (phaseAInc + 3584)% 5376;

p_A = sin768 [phaseAInc] << 1; // consulte PIOC: PC1 a PC8, pino Arduino Due correspondente: pino 33-40, portanto, mude para a esquerda para 1 dígito

p_B = sin768 [phaseBInc] << 12; // consulte PIOC: PC12 para PC19, pino Arduino Due correspondente: pino 51-44, portanto, desloque 12 dígitos para a esquerda

p_C = sin768 [phaseCInc]; // saída de fase C empregar PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 e PC29, pino Arduino Due correspondente: pino digital: 9, 8, 7, 6, 5, 4, 3, 10, respectivamente

p_C2 = (p_C & B11000000) << 22; // isso gera PC28 e PC29

p_C3 = (p_C & B00111111) << 21; // isso gera PC21-PC26

p_C = p_C2 | p_C3; // isso gera saída paralela da fase C

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

PIOC-> PIO_ODSR = p_A; // registro de saída = p_A

t ++; }

Etapa 4: R / 2R DAC

construir 3x8bit R / 2R DAC, cargas de ref no google.

Etapa 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; // valor da fase C da fase A da fase B - embora a saída seja apenas de 8 bits, os valores p_A e p_B serão operados para gerar um novo valor de 32 bits a fim de lidar com a saída PIOC de 32 bits

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; intervalo uint32_t; amostras uint16_t, predefinidas; uint32_t t = 0;

void setup () {

// configuração PIOC de saída paralela: Arduino Due pinos 33-40 são empregados como saída de fase A enquanto o pino 44-51 trabalha para saída de fase B

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO controlador PIO Enable register (consulte a p656 da folha de dados ATMEL SAM3X) e https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pino 33-41 e 44-51 foram habilitados

PIOC-> PIO_OER = 0xFFFFFFFE; // Registro de ativação de saída do controlador PIO, consulte a p657 da folha de dados ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // Registro de status de saída do controlador PIO, consulte a p658 da folha de dados ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // Registro de habilitação de gravação de saída PIO, consulte a p670 da folha de dados ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // opcional como seguro, não parece afetar o desempenho, pino digital 10 conecta a PC29 e PA28, pino digital 4 conecta a PC29 e PA28, aqui para desativar desabilitar PIOA # 28 e 29 // configuração do temporizador, consulte https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (false); // desativa a proteção contra gravação de registros de controle de gerenciamento de energia

pmc_enable_periph_clk (ID_TC7); // habilita o contador de tempo 7 do relógio periférico

TC_Configure (/ * clock * / TC2, / * canal * / 1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // Relógio TC 42MHz (relógio, canal, configuração do modo de comparação) TC_SetRC (TC2, 1, intervalo); TC_Start (TC2, 1);

// habilita interrupções do temporizador no temporizador TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = registro de habilitação de interrupção TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = interromper o registro de desabilitação

NVIC_EnableIRQ (TC7_IRQn); // Habilita a interrupção no controlador de interrupção vetorial aninhado freq = 60; // inicializa a frequência como 60 Hz predefinido = 21; // aumento do índice da matriz em 21 amostras = 256; // saída de amostras 256 / intervalo de ciclo = 42000000 / (freq * samples); // interrupções contagens TC_SetRC (TC2, 1, intervalo); // inicia TC Serial.begin (9600); // para fins de teste}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} else

{freq = freqNew;

if (freq> 20000) {freq = 20000; / * frequência máxima 20kHz * /};

if (freq <1) {freq = 1; / * frequência mínima 1 Hz * /};

if (freq> 999) {preset = 384; samples = 14;} // para frequência> = 1kHz, 14 amostras para cada ciclo

else if (freq> 499) {preset = 84; samples = 64;} // para 500 <= frequência99) {preset = 42; samples = 128;} // para 100Hz <= frequência <500Hz, 128 samples / ciclo

senão {predefinição = 21; amostras = 256;}; // para frequência <100 Hz, 256 amostras para cada ciclo

intervalo = 42000000 / (amostras de frequência *); t = 0; TC_SetRC (TC2, 1, intervalo); }}

void loop () {

checkFreq (); atraso (100); }

void TC7_Handler (void)

{TC_GetStatus (TC2, 1);

t = t% amostras; // use t% samples para evitar overflow de t phaseAInc = (preset * t)% 5376; // use% 5376 para evitar estouro de índice de array

phaseBInc = (phaseAInc + 1792)% 5376;

phaseCInc = (phaseAInc + 3584)% 5376;

p_A = sin768 [phaseAInc] << 1; // consulte PIOC: PC1 a PC8, pino Arduino Due correspondente: pino 33-40, portanto, mude para a esquerda para 1 dígito

p_B = sin768 [phaseBInc] << 12; // consulte PIOC: PC12 para PC19, pino Arduino Due correspondente: pino 51-44, portanto, desloque 12 dígitos para a esquerda

p_C = sin768 [phaseCInc]; // saída de fase C empregar PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 e PC29, pino Arduino Due correspondente: pino digital: 9, 8, 7, 6, 5, 4, 3, 10, respectivamente

p_C2 = (p_C & B11000000) << 22; // isso gera PC28 e PC29

p_C3 = (p_C & B00111111) << 21; // isso gera PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // isso gera saída paralela da fase C

p_A = p_A | p_B | p_C; // saída 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 saída = p_A t ++; }

Recomendado: