Bonjour,
Je suis actuellement en stage, pour ma 3ème année d'Ecole d'ingénieurs, en Espagne.
Je m'excuse d'avance pour le long post mais j'aurais voulu trouver les réponses par moi même du coup j'ai accumulé les question
Je dois faire améliorer une carte déjà existante pour contrôler un Moteur triphasé, je dois donc générer 7 signaux PWM, ce qui est fait mais a son importance. Je dois aussi compter le nombre de tours que fais l'encoder du Moteur, qui va a 67.5KHz.
N'étant encore qu'en phase de test, je dois moi même générer le signal en quadrature, ce que j'ai réussi, mais je n'arrive pas à comprendre suffisamment les code pour changer les pins de sortie.
Je dois également lire le sens et la vitesse de l'encoder.
Voila donc pour résumé :
- Comment changer les pins dans le code ci dessous ?
- Comment marche les registres du code ?
- Est ce que l'Arduino DUE est capable de faire fonctionner 6 PWM en même temps avec sa fonction d'interruption : PWM_Handler(); et lire un Encoder à 67.5Khz sans qu'il y ai de pertes?
Code pour l'émulateur du signal en Quadrature :
// Emulador de un encoder incremental
// - señal A: pines 6 y 7
// - señal B: pines 8 y 9
// - señal index: 34 y 35
// basado en: http://forum.arduino.cc/index.php?topic=161192.0;wap2
#define MAX_FREQ 100000
#define RESOLUCION 2000
#define DUTY_100 255
float freq;
int cont;
void pwmWrite(uint32_t ulFreq) {
int duty_100 = DUTY_100;
int duty_75 = (((duty_100+1)/4)*3)-1;
int duty_50 = ((duty_100+1)/2)-1;
int duty_25 = ((duty_100+1)/4)-1;
pmc_enable_periph_clk(ID_PWM);
PWMC_ConfigureClocks(ulFreq * duty_100, 0, VARIANT_MCK ); // (frec cont A, frec cont B, master clock)
// Canales PWM que vamos a usar:
uint32_t chan6 = g_APinDescription[6].ulPWMChannel;
uint32_t chan7 = g_APinDescription[7].ulPWMChannel;
uint32_t chan8 = g_APinDescription[8].ulPWMChannel;
uint32_t chan9 = g_APinDescription[9].ulPWMChannel;
// usaremos los pines 6, 7, 8 y 9
PIO_Configure(g_APinDescription[6].pPort, g_APinDescription[6].ulPinType, g_APinDescription[6].ulPin, g_APinDescription[6].ulPinConfiguration);
PIO_Configure(g_APinDescription[7].pPort, g_APinDescription[7].ulPinType, g_APinDescription[7].ulPin, g_APinDescription[7].ulPinConfiguration);
PIO_Configure(g_APinDescription[8].pPort, g_APinDescription[8].ulPinType, g_APinDescription[8].ulPin, g_APinDescription[8].ulPinConfiguration);
PIO_Configure(g_APinDescription[9].pPort, g_APinDescription[9].ulPinType, g_APinDescription[9].ulPin, g_APinDescription[9].ulPinConfiguration);
PIO_Configure(PIOC,PIO_PERIPH_B,PIO_PC2B_PWML0,PIO_DEFAULT); // pin PC2 (dig34 en arduino) en configuración B -> PWML0
PIO_Configure(PIOC,PIO_PERIPH_B,PIO_PC3B_PWMH0,PIO_DEFAULT); // pin PC3 (dig35 en arduino) en configuración B -> PWMH0
// CONFIGURE CHANNELS
PWMC_ConfigureChannel(PWM, chan6, PWM_CMR_CPRE_CLKA, 0, 0);
PWMC_ConfigureChannel(PWM, chan7, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
PWMC_ConfigureChannel(PWM, chan8, PWM_CMR_CPRE_CLKA, 0, 0);
PWMC_ConfigureChannel(PWM, chan9, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
// SET PERIODS
PWMC_SetPeriod(PWM, chan6, duty_100);
PWMC_SetPeriod(PWM, chan7, duty_100);
PWMC_SetPeriod(PWM, chan8, duty_100);
PWMC_SetPeriod(PWM, chan9, duty_100);
// SET DUTY CYCLES
PWMC_SetDutyCycle(PWM, chan6, duty_50);
PWMC_SetDutyCycle(PWM, chan7, duty_50);
PWMC_SetDutyCycle(PWM, chan8, duty_75);
PWMC_SetDutyCycle(PWM, chan9, duty_75);
//SET DEAD TIME
PWM->PWM_CH_NUM[chan8].PWM_CMR |= PWM_CMR_DTE; // added, enable channel dead time DTE=1
PWM->PWM_CH_NUM[chan9].PWM_CMR |= PWM_CMR_DTE;
PWMC_SetDeadTime(PWM, chan8, 0, duty_25);
PWMC_SetDeadTime(PWM, chan9, 0, duty_25);
//SYNC CHANNELS
PWMC_ConfigureSyncChannel(PWM, ( PWM_SCM_SYNC4 | PWM_SCM_SYNC5 | PWM_SCM_SYNC6 | PWM_SCM_SYNC7), PWM_SCM_UPDM_MODE0, 0, 0);
PWMC_SetSyncChannelUpdateUnlock(PWM); // PWM_SCUC set UPDULOCK to 1, update next period
PWMC_SetSyncChannelUpdatePeriod(PWM, duty_100); // update period of the synchronous channels PWM_SCUP
// SET CHANNEL 0 FOR SYNC
PWMC_ConfigureChannel(PWM, 0, PWM_CMR_CPRE_CLKA, 0, 0);
PWMC_SetPeriod(PWM, 0, duty_100);
PWMC_SetDutyCycle(PWM, 0, duty_50);
// SET PWM INTERRUPTION
NVIC_EnableIRQ(PWM_IRQn);
PWM->PWM_IER1=1; // es lo mismo que PWMC_EnableChannelIt(PWM,0); // lanzamos int al final del periodo del canal 0
PWMC_SetDutyCycle(PWM, 6, duty_50);
PWMC_EnableChannel(PWM, 0);
return;
}
void PWM_Handler(){
uint32_t ref=PWM->PWM_ISR1; // desactivamos int, si ha sido lanzada por IER1 (por ejemplo, al final del periodo)
cont++;
PWMC_SetSyncChannelUpdateUnlock(PWM); // PWM_SCUC set UPDULOCK to 1, update next period
if(cont==RESOLUCION) {
cont=0;
PWMC_SetDutyCycle(PWM, 0, DUTY_100*0.5);
digitalWrite(13,1);
} else {
PWMC_SetDutyCycle(PWM, 0, DUTY_100*0);
digitalWrite(13,0);
}
}
void setup() {
pinMode(13,OUTPUT);
Serial.begin(9600);
pwmWrite(65000);
}
void loop() {
delay(500);
}
Merci et encore désolé pour un si long post.
Les commentaires sont en espagnols mais sont simples à comprendre.