Sommario:

Generatore di onda sinusoidale trifase basato su Arduino Due: 5 passaggi
Generatore di onda sinusoidale trifase basato su Arduino Due: 5 passaggi

Video: Generatore di onda sinusoidale trifase basato su Arduino Due: 5 passaggi

Video: Generatore di onda sinusoidale trifase basato su Arduino Due: 5 passaggi
Video: Come Costruire un Inverter Monofase Trifase SPWM con Arduino / STM32 - Fai Da Te 2024, Dicembre
Anonim
Generatore di onda sinusoidale trifase basato su Arduino Due
Generatore di onda sinusoidale trifase basato su Arduino Due

lo scopo di questa condivisione è aiutare qualcuno che sta cercando di utilizzare le maggiori prestazioni di Due + mancanza di riferimento + scheda tecnica non utile.

questo progetto è in grado di generare fino a 3 fasi sinusoidali @ 256 campioni/ciclo a bassa frequenza (<1kHz) e 16 campioni/ciclo ad alta frequenza (fino a 20kHz), che è abbastanza buono da essere livellato da semplici LPF e dal l'uscita è quasi perfetta.

il file allegato non era la mia versione finale perché ho aggiunto alcune funzionalità aggiuntive ma il nucleo è lo stesso. Notare che i campioni/ciclo è stato impostato su un valore inferiore rispetto a quanto indicato sopra.

poiché la capacità della CPU è massimizzata attraverso l'approccio mostrato nel file allegato, ho usato un Arduino Uno come unità di controllo, che utilizza l'interrupt esterno di Arduino Due per passare il valore di frequenza ad Arduino Due. Oltre al controllo della frequenza, Arduino Uno controlla anche l'ampiezza (tramite il misuratore di potenziale digitale + OpAmp) e l'I/O --- ci sarà molto spazio con cui giocare.

Passaggio 1: genera un array di dati sinusoidali

Poiché il calcolo in tempo reale richiede CPU, è necessario un array di dati sinusoidali per prestazioni migliori

uint32_t sin768 PROGMEM= ….while x=[0:5375]; y = 127+127*(sin(2*pi/5376/*o qualche # che preferisci dipende dal requisito*/))

Passaggio 2: abilitazione dell'uscita parallela

A differenza di Uno, Due hanno riferimenti limitati. Tuttavia, per generare un'onda sinusoidale trifase basata su Arduino Uno, prima di tutto, le prestazioni non sono applaudibili a causa del suo basso MCLK (16 MHz mentre Due è 84 MHz), in secondo luogo, il GPIO limitato può produrre un massimo di 2 fasi e hai bisogno di ulteriori circuito analogico per produrre la 3° fase (C=-AB).

Dopo l'abilitazione GPIO si basava principalmente su prova e prova + scheda tecnica non utile di SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; //PIO controller PIO Enable register (fare riferimento a p656 del datasheet di ATMEL SAM3X) e https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 e 44-51 sono stati abilitati

PIOC->PIO_OER = 0xFFFFFFFE; //Registro di abilitazione uscita controller PIO, vedere p657 del foglio dati ATMEL SAM3X PIOC->PIO_OSR = 0xFFFFFFFE; //Registro di stato dell'uscita del controller PIO, fare riferimento a p658 del foglio dati ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //Registro di abilitazione scrittura uscita PIO, fare riferimento a p670 del foglio dati ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //opzionale come assicurazione, non sembra influire sulle prestazioni, il pin digitale 10 si collega a PC29 e PA28, il pin digitale 4 si collega sia a PC29 che a PA28, qui per disabilitare disabilitare PIOA #28 e 29

Passaggio 3: abilitazione dell'interruzione

Per massimizzare le sue prestazioni, il carico della CPU dovrebbe essere il più basso possibile. Tuttavia, a causa della corrispondenza non-1to1 tra il pin della CPU e il pin Due, è necessaria l'operazione a bit.

Puoi ottimizzare ulteriormente l'algoritmo ma la stanza è molto limitata.

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

t = t%campioni; // usa t%samples invece di 'if' per evitare l'overflow di t

phaseAInc = (preset*t)%5376; // usa %5376 per evitare l'overflow dell'indice dell'array

faseBInc = (faseAInc+1792)%5376;

faseCInc = (faseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; //fare riferimento a PIOC: da PC1 a PC8, corrispondente pin Arduino Due: pin 33-40, quindi spostare a sinistra per 1 cifra

p_B = sin768[phaseBInc]<<12; //fare riferimento a PIOC: da PC12 a PC19, corrispondente pin Arduino Due: pin 51-44, quindi spostare a sinistra di 12 cifre

p_C = sin768[phaseCInc]; //uscita fase C impiega PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 e PC29, pin Arduino Due corrispondente: pin digitale: 9, 8, 7, 6, 5, 4, 3, 10, rispettivamente

p_C2 = (p_C&B11000000)<<22; //questo genera PC28 e PC29

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

p_C = p_C2|p_C3; //questo genera un'uscita parallela della fase C

p_A = p_A|p_B|p_C; //Uscita 32 bit = fase A (8bit)|fase B|fase C

PIOC->PIO_ODSR = p_A; //registro di uscita =p_A

t++; }

Passaggio 4: DAC R/2R

costruire 3x8bit R/2R DAC, un sacco di ref su google.

Passaggio 5: codice completo

#define _BV(x) (1<<(x)); uint32_t sin768 PROGMEM= /* x=[0:5375]; y = 127+127*(peccato(2*pi/5376)) */

uint32_t p_A, p_B, p_C, p_C2, p_C3; // valore fase A fase B fase C - sebbene l'uscita sia solo a 8 bit, il valore p_A e p_B verrà utilizzato per generare un nuovo valore a 32 bit per far fronte all'uscita PIOC a 32 bit

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t intervallo; uint16_t campioni, preset; uint32_t t = 0;

void setup() {

//configurazione PIOC dell'uscita parallela: i pin33-40 di Arduino Due sono utilizzati come uscita di fase A mentre i pin 44-51 funzionano per l'uscita di fase B

PIOC->PIO_PER = 0xFFFFFFFE; //PIO controller PIO Enable register (fare riferimento a p656 del datasheet di ATMEL SAM3X) e https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 e 44-51 sono stati abilitati

PIOC->PIO_OER = 0xFFFFFFFE; //Registro di abilitazione uscita controller PIO, fare riferimento a p657 del foglio dati ATMEL SAM3X

PIOC->PIO_OSR = 0xFFFFFFFE; //Registro di stato dell'uscita del controller PIO, fare riferimento a p658 del foglio dati ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //Registro di abilitazione scrittura uscita PIO, fare riferimento a p670 del foglio dati ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //opzionale come assicurazione, non sembra influire sulle prestazioni, il pin digitale 10 si collega sia a PC29 che a PA28, il pin digitale 4 si collega a PC29 e PA28, qui per disabilitare disabilitare PIOA #28 e 29 // setup timer, fare riferimento a https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect(false); // disabilita la protezione da scrittura dei registri di Power Management Control

pmc_enable_periph_clk(ID_TC7); // abilita il contatore del tempo dell'orologio periferico 7

TC_Configure(/* orologio */TC2, /* canale */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //TC clock 42MHz (clock, canale, impostazione modalità confronto) TC_SetRC(TC2, 1, interval); TC_Start(TC2, 1);

// abilita gli interrupt del timer sul timer TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = registro abilitazione interrupt TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = registro di disabilitazione degli interrupt

NVIC_EnableIRQ(TC7_IRQn); // Abilita l'interrupt nel controller di interrupt del vettore annidato freq = 60; //inizializza la frequenza come preset 60Hz = 21; //incremento dell'indice dell'array di 21 campioni = 256; //campioni di output 256/intervallo di ciclo = 42000000/(freq*samples); //interrupt conta TC_SetRC(TC2, 1, intervallo); //avvia TC Serial.begin(9600); //a scopo di test }

void checkFreq()

{freqNuova = 20000;

if (freq == freqNew) {} else

{ freq = freqNew;

if (freq>20000) {freq = 20000; /*frequenza massima 20kHz*/};

if (freq<1) {freq=1; /*frequenza minima 1Hz*/};

if (freq>999) {preimpostato = 384; campioni = 14;} //per frequenza >=1kHz, 14 campioni per ogni ciclo

else if (freq>499) {preset = 84; campioni = 64;} //per 500<=frequenza99) {preimpostato = 42; campioni = 128;} //per 100Hz<=frequenza<500Hz, 128 campioni/ciclo

else {preimpostato = 21; campioni = 256;}; //per frequenza<100hz, 256 campioni per ogni ciclo

intervallo = 42000000/(freq*campioni); t = 0; TC_SetRC(TC2, 1, intervallo); } }

ciclo vuoto() {

checkFreq(); ritardo(100); }

void TC7_Handler(void)

{ TC_GetStatus(TC2, 1);

t = t%campioni; //usa t%samples per evitare l'overflow di t phaseAInc = (preset*t)%5376; // usa %5376 per evitare l'overflow dell'indice dell'array

faseBInc = (faseAInc+1792)%5376;

faseCInc = (faseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; //fare riferimento a PIOC: da PC1 a PC8, corrispondente pin Arduino Due: pin 33-40, quindi spostare a sinistra per 1 cifra

p_B = sin768[phaseBInc]<<12; //fare riferimento a PIOC: da PC12 a PC19, corrispondente pin Arduino Due: pin 51-44, quindi spostare a sinistra di 12 cifre

p_C = sin768[phaseCInc]; //uscita fase C impiega PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 e PC29, pin Arduino Due corrispondente: pin digitale: 9, 8, 7, 6, 5, 4, 3, 10, rispettivamente

p_C2 = (p_C&B11000000)<<22; //questo genera PC28 e PC29

p_C3 = (p_C&B00111111)<<21; //questo genera PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2|p_C3; //questo genera un'uscita parallela della fase C

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

PIOC->PIO_ODSR = p_A; //registro di uscita =p_A t++; }

Consigliato: