Table des matières:

Générateur d'onde sinusoïdale triphasée basé sur Arduino Due : 5 étapes
Générateur d'onde sinusoïdale triphasée basé sur Arduino Due : 5 étapes

Vidéo: Générateur d'onde sinusoïdale triphasée basé sur Arduino Due : 5 étapes

Vidéo: Générateur d'onde sinusoïdale triphasée basé sur Arduino Due : 5 étapes
Vidéo: Onduleur avec Arduino #5: Commande SPWM - Partie 3 (la dernière) [TUTO] 2024, Juillet
Anonim
Générateur d'onde sinusoïdale triphasée basé sur Arduino Due
Générateur d'onde sinusoïdale triphasée basé sur Arduino Due

le but de ce partage est d'aider quelqu'un qui essaie d'utiliser les meilleures performances de Due + le manque de référence + la fiche technique non utile.

ce projet est capable de générer jusqu'à 3 phases d'onde sinusoïdale à 256 échantillons/cycle à basse fréquence (<1 kHz) et 16 échantillons/cycle à haute fréquence (jusqu'à 20 kHz), ce qui est assez bon pour être lissé par de simples LPF et le le rendu est presque parfait.

le fichier joint n'était pas ma version finale car j'ai ajouté des fonctionnalités supplémentaires, mais le noyau est le même. Notez que le nombre d'échantillons/cycle a été défini plus bas que la déclaration ci-dessus.

étant donné que la capacité du processeur est maximisée grâce à l'approche indiquée dans le fichier joint, j'ai utilisé un Arduino Uno comme unité de contrôle, qui utilise l'interruption externe d'Arduino Due pour transmettre la valeur de fréquence à Arduino Due. En plus du contrôle de fréquence, l'Arduino Uno contrôle également l'amplitude (via un potentiel-mètre numérique + OpAmp) ainsi que les E/S --- il y aura beaucoup de place pour jouer avec.

Étape 1: Générer un tableau de données sinusoïdales

Étant donné que le calcul en temps réel est exigeant en CPU, une matrice de données sinusoïdales est requise pour de meilleures performances

uint32_t sin768 PROGMEM= ….while x=[0:5375]; y = 127+127*(sin(2*pi/5376/*ou quelque # que vous préférez dépend de l'exigence*/))

Étape 2: Activation de la sortie parallèle

Contrairement à Uno, Due a une référence limitée. Cependant, afin de générer une onde sinusoïdale triphasée basée sur Arduino Uno, 1er de tous, les performances ne sont pas appréciables en raison de son faible MCLK (16MHz tandis que Due est de 84MHz), 2ème, il est limité GPIO peut produire une sortie maximale de 2 phases et vous avez besoin de plus circuit analogique pour produire la 3ème phase (C=-AB).

La suite de l'activation de GPIO était principalement basée sur un essai et une fiche technique non utile de SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; // Contrôleur PIO Registre d'activation PIO (voir p656 de la fiche technique ATMEL SAM3X) et https://arduino.cc/en/Hacking/PinMappingSAM3X, les broches Arduino Due 33-41 et 44-51 ont été activées

PIOC->PIO_OER = 0xFFFFFFFE; //Registre d'activation de la sortie du contrôleur PIO, reportez-vous à p657 de la fiche technique ATMEL SAM3X PIOC->PIO_OSR = 0xFFFFFFFE; //Registre d'état de sortie du contrôleur PIO, voir p658 de la fiche technique ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //Registre d'activation d'écriture de sortie PIO, reportez-vous à p670 de la fiche technique ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //optionnel comme assurance, ne semble pas affecter les performances, la broche numérique 10 se connecte à la fois au PC29 et au PA28, la broche numérique 4 se connecte à la fois au PC29 et au PA28, ici pour désactiver désactiver PIOA #28 & 29

Étape 3: Activation de l'interruption

Pour maximiser ses performances, la charge CPU doit être aussi faible que possible. Cependant, en raison de la correspondance non 1 à 1 entre la broche CPU et la broche Due, une opération sur les bits est nécessaire.

Vous pouvez encore optimiser l'algorithme mais la place est très limitée.

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

t = t% échantillons; //utiliser t%samples au lieu de 'if' pour éviter le débordement de t

phaseAInc = (prédéfini*t)%5376; //utiliser %5376 pour éviter le débordement de l'index du tableau

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; // se référer à PIOC: PC1 à PC8, broche Arduino Due correspondante: broche 33-40, donc décaler à gauche pour 1 chiffre

p_B = sin768[phaseBInc]<<12; // se référer à PIOC: PC12 à PC19, broche Arduino Due correspondante: broche 51-44, donc décaler à gauche 12 chiffres

p_C = sin768[phaseCInc]; // sortie phase C employe PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 et PC29, broche Arduino Due correspondante: broche numérique: 9, 8, 7, 6, 5, 4, 3, 10, respectivement

p_C2 = (p_C&B11000000)<<22; //cela génère PC28 et PC29

p_C3 = (p_C&B00111111)<<21; //cela génère PC21-PC26

p_C = p_C2|p_C3; //cela génère une sortie parallèle de la phase C

p_A = p_A|p_B|p_C; //sortie 32 bits = phase A (8 bits)|phase B|phase C

PIOC->PIO_ODSR = p_A; //registre de sortie =p_A

t++; }

Étape 4: DAC R/2R

build 3x8bit R/2R DAC, beaucoup de références sur google.

Étape 5: Code complet

#définir _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; //phase A phase B phase C valeur - bien que la sortie ne soit que de 8 bits, les valeurs p_A et p_B seront utilisées pour générer une nouvelle valeur de 32 bits afin de gérer la sortie PIOC de 32 bits

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; uint32_t intervalle; échantillons uint16_t, prédéfinis; uint32_t t = 0;

void setup() {

//Configuration PIOC de sortie parallèle: les broches 33-40 Arduino Due sont utilisées comme sortie de phase A tandis que les broches 44-51 fonctionnent pour la sortie de phase B

PIOC->PIO_PER = 0xFFFFFFFE; // Contrôleur PIO Registre d'activation PIO (voir p656 de la fiche technique ATMEL SAM3X) et https://arduino.cc/en/Hacking/PinMappingSAM3X, les broches Arduino Due 33-41 et 44-51 ont été activées

PIOC->PIO_OER = 0xFFFFFFFE; //Registre d'activation de la sortie du contrôleur PIO, reportez-vous à p657 de la fiche technique ATMEL SAM3X

PIOC->PIO_OSR = 0xFFFFFFFE; //Registre d'état de sortie du contrôleur PIO, voir p658 de la fiche technique ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //Registre d'activation d'écriture de sortie PIO, reportez-vous à p670 de la fiche technique ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; //facultatif comme assurance, ne semble pas affecter les performances, la broche numérique 10 se connecte à la fois au PC29 et au PA28, la broche numérique 4 se connecte à la fois au PC29 et au PA28, ici pour désactiver la PIOA #28 & 29 //configuration de la minuterie, reportez-vous à https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect(false); // désactiver la protection en écriture des registres de contrôle de gestion de l'alimentation

pmc_enable_periph_clk(ID_TC7); // activer le compteur horaire de l'horloge périphérique 7

TC_Configure(/* horloge */TC2, /* canal */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //Horloge TC 42MHz (horloge, canal, réglage du mode de comparaison) TC_SetRC(TC2, 1, intervalle); TC_Début(TC2, 1);

// activer les interruptions du timer sur le timer TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = registre d'activation d'interruption TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = registre de désactivation d'interruption

NVIC_EnableIRQ(TC7_IRQn); // Activer l'interruption dans le contrôleur d'interruption vectorielle imbriquée freq = 60; //initialiser la fréquence en tant que préréglage 60 Hz = 21; //augmentation de l'index du tableau de 21 échantillons = 256; //sortir les échantillons 256/intervalle de cycle = 42000000/(freq*samples); //compte d'interruption TC_SetRC(TC2, 1, intervalle); //démarrer TC Serial.begin(9600); //à des fins de test }

void checkFreq()

{ freqNouveau = 20000;

if (freq == freqNew) {} else

{ freq = freqNouveau;

if (freq>20000) {freq = 20000; /*fréquence max 20kHz*/};

si (freq<1) {freq = 1; /*fréquence min 1Hz*/};

if (freq>999) {préréglé = 384; échantillons = 14;} //pour la fréquence >=1kHz, 14 échantillons pour chaque cycle

else if (freq>499) {preset = 84; échantillons = 64;} //pour 500<=fréquence99) {préréglage = 42; échantillons = 128;} //pour 100Hz<=fréquence<500Hz, 128 échantillons/cycle

else {préréglé = 21; échantillons = 256;}; //pour la fréquence<100hz, 256 échantillons pour chaque cycle

intervalle = 42000000/(freq*échantillons); t = 0; TC_SetRC(TC2, 1, intervalle); } }

boucle vide() {

vérifierFréq(); retard (100); }

void TC7_Handler(void)

{ TC_GetStatus(TC2, 1);

t = t% échantillons; //utiliser t%samples pour éviter le débordement de t phaseAInc = (preset*t)%5376; //utiliser %5376 pour éviter le débordement de l'index du tableau

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAInc]<<1; // se référer à PIOC: PC1 à PC8, broche Arduino Due correspondante: broche 33-40, donc décaler à gauche pour 1 chiffre

p_B = sin768[phaseBInc]<<12; // se référer à PIOC: PC12 à PC19, broche Arduino Due correspondante: broche 51-44, donc décaler à gauche 12 chiffres

p_C = sin768[phaseCInc]; // sortie phase C employe PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 et PC29, broche Arduino Due correspondante: broche numérique: 9, 8, 7, 6, 5, 4, 3, 10, respectivement

p_C2 = (p_C&B11000000)<<22; //cela génère PC28 et PC29

p_C3 = (p_C&B00111111)<<21; //cela génère PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2|p_C3; //cela génère une sortie parallèle de la phase C

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

PIOC->PIO_ODSR = p_A; //registre de sortie =p_A t++; }

Conseillé: