Hi,
I am working on three omniwheel robot, and I need to control 3 Dc motors with PID controller at 15 Khz PWM frequency.
For 15 Khz PWM frequency, someone helped me in this link.
To use my PID I need encoder Data, on Pin :
Motor 1 : PIN ( pwm 9, dir 2) encoder (phase A 22, Phase B 23)
Motor 2 : PIN ( pwm 10, dir 3) encoder (phase A 24, Phase B 25)
Motor 3 : PIN ( pwm 5, dir 4) encoder (phase A 26, Phase B 27)
or :
Motor 1 : PIN ( pwm 9, dir 2) encoder (phase A 22, Phase B 23)
Motor 2 : PIN ( pwm 10, dir 3) encoder (phase A 44, Phase B 55)
Motor 3 : PIN ( pwm 5, dir 4) encoder (phase A 42, Phase B 43)
Can someone help to use three encoders with interruption in Arduino Due on that'pins ? ( i saw that arduino Due got 2 encoder quadrature Pin but used from my PWM).
One way to make the TC timer code more efficient, is to only call the timers' interrupts when you need to make a change to their respective duty-cycles. This should free up more CPU time to deal with the encoders:
// Set up the Arduino Due's digital pins D5 and D10 for 15kHz PWM with RC compare interrupts
volatile uint32_t dutycycleTC6 = 0, dutycycleTC7 = 0;
void setup()
{
PMC->PMC_PCER1 |= PMC_PCER1_PID34 | PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0) and TC7 (TC2 Channel 1)
PIOC->PIO_ABSR |= PIO_ABSR_P29 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 (D5) and TIOB7 (D10)
PIOC->PIO_PDR |= PIO_PDR_P29 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins
TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0
TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0
TC_CMR_WAVE | // Enable wave mode
TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)
TC2->TC_CHANNEL[1].TC_CMR = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0
TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0
TC_CMR_WAVE | // Enable wave mode
TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)
TC2->TC_CHANNEL[0].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800
TC2->TC_CHANNEL[1].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800
NVIC_SetPriority(TC6_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC6 to 0 (highest)
NVIC_EnableIRQ(TC6_IRQn); // Connect TC6 to Nested Vector Interrupt Controller (NVIC)
TC2->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt for TC6 (TC2 Channel 0)
NVIC_SetPriority(TC7_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC7 to 0 (highest)
NVIC_EnableIRQ(TC7_IRQn); // Connect TC7 to Nested Vector Interrupt Controller (NVIC)
TC2->TC_CHANNEL[1].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt for TC7 (TC2 Channel 1)
TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6 (TC2 Channel 0)
TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC7 (TC2 Channel 1)
}
bool ChangeTC6PWMFreq(uint32_t dutycycle)
{
if (!(TC2->TC_CHANNEL[0].TC_IMR & TC_IMR_CPCS)) // Check if the RC compare interrupt for TC6 has been disabled
{
dutycycleTC6 = dutycycle;
TC2->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt for TC6 (TC2 Channel 0)
}
}
bool ChangeTC7PWMFreq(uint32_t dutycycle)
{
if (!(TC2->TC_CHANNEL[1].TC_IMR & TC_IMR_CPCS)) // Check if the RC compare interrupt for TC7 has been disabled
{
dutycycleTC7 = dutycycle;
TC2->TC_CHANNEL[1].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt for TC7 (TC2 Channel 1)
}
}
void loop()
{
ChangeTC6PWMFreq(700); // Set the duty-cycle to 25% on D5 on next timer cycle
ChangeTC7PWMFreq(700); // Set the duty-cycle to 25% on D10 on next timer cycle
delay(2000); // Wait for 2 seconds
ChangeTC6PWMFreq(2100); // Set the duty-cycle to 75% on D5 on next timer cycle
ChangeTC7PWMFreq(2100); // Set the duty-cycle to 75% on D10 on next timer cycle
delay(2000); // Wait for 2 seconds
}
void TC6_Handler() // ISR TC6 (TC2 Channel 0)
{
if (TC2->TC_CHANNEL[0].TC_SR & TC_SR_CPCS) // Check for RC compare condition
{
TC2->TC_CHANNEL[0].TC_RA = dutycycleTC6; // Set the duty-cycle to on D5
TC2->TC_CHANNEL[0].TC_IDR = TC_IDR_CPCS; // Disable RC compare interrupt for TC6 (TC2 Channel 0)
}
}
void TC7_Handler() // ISR TC7 (TC2 Channel 1)
{
if (TC2->TC_CHANNEL[1].TC_SR & TC_SR_CPCS) // Check for RC compare condition
{
TC2->TC_CHANNEL[1].TC_RB = dutycycleTC7; // Set the duty-cycle on 10
TC2->TC_CHANNEL[1].TC_IDR = TC_IDR_CPCS; // Disable RC compare interrupt for TC7 (TC2 Channel 1)
}
}