Innehållsförteckning:

3 -fas sinusgenerator baserad på Arduino Due: 5 steg
3 -fas sinusgenerator baserad på Arduino Due: 5 steg

Video: 3 -fas sinusgenerator baserad på Arduino Due: 5 steg

Video: 3 -fas sinusgenerator baserad på Arduino Due: 5 steg
Video: How to use 4 channel Relay to control AC load with Arduino code 2024, Juli
Anonim
3 -fas sinusgenerator baserad på Arduino Due
3 -fas sinusgenerator baserad på Arduino Due

syftet med denna aktie är att hjälpa någon som försöker använda Due högre prestanda + brist på referens + icke-användbart datablad.

detta projekt kan generera upp till 3 -fas sinusvåg @ 256 samplingar / cykel vid låg frekvens (<1 kHz) och 16 sampel / cykel @ hög frekvens (upp till 20 kHz), vilket är tillräckligt bra för att utjämnas med enkla LPF: er och utgången är nästan perfekt.

den bifogade filen var inte min slutliga version för jag lade till ytterligare en funktion men kärnan är densamma. Observera att proverna/cykeln sattes lägre än ovanstående uttalande.

eftersom CPU -kapaciteten maximeras genom den metod som visas i den bifogade filen använde jag en Arduino Uno som styrenhet, som använder Arduino Due externa avbrott för att överföra frekvensvärdet till Arduino Due. Förutom frekvenskontroll, styr Arduino Uno också amplituden (genom digital potentialmätare + OpAmp) samt I/O --- det kommer att finnas mycket utrymme att leka med.

Steg 1: Generera Sine Data Array

Eftersom realtidsberäkning är CPU-krävande krävs en sinusdatamat för bättre prestanda

uint32_t sin768 PROGMEM =….under x = [0: 5375]; y = 127+127*(sin (2*pi/5376/*eller några # du föredrar beror på kravet*/))

Steg 2: Aktivera parallellutmatning

Till skillnad från Uno har Due begränsad referens. Men för att generera 3 -fas sinusvåg baserad på Arduino Uno, första av allt, är prestanda inte applausable på grund av dess låga MCLK (16MHz medan Due är 84MHz), 2: a, det är begränsat GPIO kan producera max 2 fas utgång och du behöver ytterligare analog krets för att producera den tredje fasen (C = -AB).

Att följa GPIO -aktivering baserades mestadels på försök och prov+ett användbart datablad för SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO-styrenhet PIO Aktivera register (se s. 656 i ATMEL SAM3X-datablad) och https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 och 44-51 har aktiverats

PIOC-> PIO_OER = 0xFFFFFFFE; // PIO-kontroller utmatningsregister, se p657 i ATMEL SAM3X-datablad PIOC-> PIO_OSR = 0xFFFFFFFE; // Statusregister för PIO -styrenhet, se p658 i ATMEL SAM3X -datablad

PIOC-> PIO_OWER = 0xFFFFFFFE; // PIO -utskrivningsregistreringsregister, se p670 i ATMEL SAM3X -datablad

// PIOA-> PIO_PDR = 0x30000000; // valfritt som försäkring, verkar inte påverka prestanda, digital pin 10 anslut till både PC29 och PA28, digital pin 4 anslut till både PC29 och PA28, här för att inaktivera inaktivera PIOA #28 & 29

Steg 3: Aktivera avbrott

För att maximera dess prestanda bör CPU -belastningen vara så låg som möjligt. På grund av icke-1to1-korrespondensen mellan CPU-stiftet och Due-stiftet är bitoperation dock nödvändig.

Du kan ytterligare optimera algoritmen men rummet är mycket begränsat.

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

t = t%prover; // använd t%-prover istället för 'om' för att undvika överflöd av t

phaseAInc = (förinställd*t)%5376; // använd %5376 för att undvika övermatning av arrayindex

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // hänvisa till PIOC: PC1 till PC8, motsvarande Arduino Due-stift: stift 33-40, därefter växla vänster för 1 siffra

p_B = sin768 [phaseBInc] << 12; // se PIOC: PC12 till PC19, motsvarande Arduino Due-stift: stift 51-44, därav växla vänster 12-siffrig

p_C = sin768 [phaseCInc]; // fas C -utgång använder PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 och PC29, motsvarande Arduino Due pin: digital pin: 9, 8, 7, 6, 5, 4, 3, 10, respektive

p_C2 = (p_C & B11000000) << 22; // detta genererar PC28 och PC29

p_C3 = (p_C & B00111111) << 21; // detta genererar PC21-PC26

p_C = p_C2 | p_C3; // detta genererar parallell utmatning av fas C

p_A = p_A | p_B | p_C; // 32 bitars utgång = fas A (8bit) | fas B | fas C

PIOC-> PIO_ODSR = p_A; // utmatningsregister = p_A

t ++; }

Steg 4: R/2R DAC

bygg 3x8bit R/2R DAC, massor av ref på google.

Steg 5: Fullständig kod

#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; // fas A fas B fas C-värde-även om utdata bara är 8 bitar, kommer p_A och p_B-värdet att drivas för att generera ett nytt 32 bitars värde för att klara av 32bit PIOC-utdata

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t intervall; uint16_t prover, förinställda; uint32_t t = 0;

void setup () {

// parallellutgång PIOC-inställning: Arduino Due pin33-40 används som fas A-utgång medan stift 44-51 fungerar för fas B-utgång

PIOC-> PIO_PER = 0xFFFFFFFE; // PIO-styrenhet PIO Aktivera register (se s. 656 i ATMEL SAM3X-datablad) och https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 och 44-51 har aktiverats

PIOC-> PIO_OER = 0xFFFFFFFE; // PIO -kontroller utmatningsregister, se p657 i ATMEL SAM3X -datablad

PIOC-> PIO_OSR = 0xFFFFFFFE; // Statusregister för PIO -styrenhet, se p658 i ATMEL SAM3X -datablad

PIOC-> PIO_OWER = 0xFFFFFFFE; // PIO -utskrivningsregistreringsregister, se p670 i ATMEL SAM3X -datablad

// PIOA-> PIO_PDR = 0x30000000; // valfritt som försäkring, verkar inte påverka prestanda, digital pin 10 ansluta till både PC29 och PA28, digital pin 4 ansluta till både PC29 och PA28, här för att inaktivera inaktivera PIOA #28 & 29 // timerinställning, se https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (false); // inaktivera skrivskydd för Power Management Control -registren

pmc_enable_periph_clk (ID_TC7); // aktivera perifer klockans tidräknare 7

TC_Configure (/ * clock */TC2,/ * channel */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); // TC -klocka 42MHz (klocka, kanal, jämförlägesinställning) TC_SetRC (TC2, 1, intervall); TC_Start (TC2, 1);

// aktivera timeravbrott på timern TC2-> TC_CHANNEL [1]. TC_IER = TC_IER_CPCS; // IER = avbryt aktiveringsregister TC2-> TC_CHANNEL [1]. TC_IDR = ~ TC_IER_CPCS; // IDR = avbryt inaktivera register

NVIC_EnableIRQ (TC7_IRQn); // Aktivera avbrottet i den kapslade vektoravbrottsstyrenhetens frekvens = 60; // initiera frekvensen som 60Hz förinställd = 21; // arrayindex ökning med 21 samplingar = 256; // utdata prover 256/cykelintervall = 42000000/(frekv*prov); // avbrott räknar TC_SetRC (TC2, 1, intervall); // starta TC Serial.begin (9600); // för teständamål}

void checkFreq ()

{freqNew = 20000;

if (freq == freqNew) {} annat

{freq = freqNew;

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

om (freq <1) {freq = 1; /*min frekvens 1Hz*/};

if (freq> 999) {förinställd = 384; samplar = 14;} // för frekvens> = 1kHz, 14 sampel för varje cykel

annars om (freq> 499) {förinställd = 84; samplar = 64;} // för 500 <= frekvens99) {förinställd = 42; samplar = 128;} // för 100Hz <= frekvens <500Hz, 128 sampel/cykel

annars {förinställt = 21; prover = 256;}; // för frekvens <100 Hz, 256 samplingar för varje cykel

intervall = 42000000/(frekv*prov); t = 0; TC_SetRC (TC2, 1, intervall); }}

void loop () {

checkFreq (); fördröjning (100); }

void TC7_Handler (void)

{TC_GetStatus (TC2, 1);

t = t%prover; // använd t%-prover för att undvika överflöd av t phaseAInc = (förinställt*t)%5376; // använd %5376 för att undvika övermatning av arrayindex

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // hänvisa till PIOC: PC1 till PC8, motsvarande Arduino Due-stift: stift 33-40, därefter växla vänster för 1 siffra

p_B = sin768 [phaseBInc] << 12; // se PIOC: PC12 till PC19, motsvarande Arduino Due-stift: stift 51-44, därav växla vänster 12-siffrigt

p_C = sin768 [phaseCInc]; // fas C -utgång använder PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 och PC29, motsvarande Arduino Due pin: digital pin: 9, 8, 7, 6, 5, 4, 3, 10, respektive

p_C2 = (p_C & B11000000) << 22; // detta genererar PC28 och PC29

p_C3 = (p_C & B00111111) << 21; // detta genererar PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2 | p_C3; // detta genererar parallell utmatning av fas C

p_A = p_A | p_B | p_C; // 32 bitars utgång = fas A (8bit) | fas B | fas C //Serial.println(p_A>>21, BIN); // PIOC-> PIO_ODSR = 0x37E00000;

PIOC-> PIO_ODSR = p_A; // utmatningsregister = p_A t ++; }

Rekommenderad: