I'm trying to generate pwm signal for my robot.
Here is my configuration:
- ChibiOS 16.1.5
- Arduino Mega2560
I want to have 4 pwm signals, 2/motors:
Motor 1, pwm pins are PE5 (arduino D3) and PE4 (arduino D2)
Motor 2, pwm pins are PH5 (arduino D8) and PH3 (arduino D6)
First off all I want to tell that I have modify the pwm_lld.c driver file to fit my need.
I'm able to generate all the 4 pwm signals when I use the configuration mode (FAST PWM with fixed frequency).
In that case, I use a prescaler of 64 that give me pwm period of 4ms. Nice but I need to have pwm with a period of 2ms to control my motors.
That why I have modify the driver. And here is my problem. After modifying the driver, I can generate a pwm signal of 2ms of period for:
pins PE5 and PE4. That pins use the Time 3.
But the strange things is that the same logic for the pins PH5 and PH3 don't work, I don't have any signals on that pins.
I'm using an oscilloscope to verify the signal generate.
Did some one have an idea of what is going on?
Here is the code where the selection of the mode is made:
Code: Select all
void pwm_lld_init(void)
{
#define FAST_MODE_FIX_FREQ 3
#define FAST_MODE_VAR_FREQ 7
uint8_t pwm_mode = FAST_MODE_VAR_FREQ;
#if AVR_PWM_USE_TIM1 || defined(__DOXYGEN__)
pwmObjectInit(&PWMD1);
PWMD1.channels = PWM_CHANNELS;
TCCR1A = (1 << WGM11) | (1 << WGM10);
TCCR1B = (0 << WGM13) | (1 << WGM12);
#endif
#if AVR_PWM_USE_TIM2 || defined(__DOXYGEN__)
pwmObjectInit(&PWMD2);
PWMD2.channels = PWM_CHANNELS;
TCCR2A = (1 << WGM21) | (1 << WGM20);
TCCR2B = (0 << WGM22);
#endif
#if AVR_PWM_USE_TIM3 || defined(__DOXYGEN__)
pwmObjectInit(&PWMD3);
PWMD3.channels = PWM_CHANNELS;
if (pwm_mode == FAST_MODE_FIX_FREQ) {
TCCR3A = (1 << WGM31) | (1 << WGM30);
TCCR3B &= ~(0 << WGM33);
TCCR3B |= (1 << WGM32);
}
if (pwm_mode == FAST_MODE_VAR_FREQ) {
uint32_t pwm_freq;
TCCR3A |= (1 << WGM31) | (1 << WGM30);
TCCR3B |= (1 << WGM33) | (1 << WGM32);
/* Calcul and set the PWM3 frequency. */
pwm_freq = 16000000/64;
// TODO: Replace 500 by PWMD3.period.
pwm_freq /= 500;
pwm_freq -= 1;
OCR3AH = (uint8_t)((pwm_freq >> 8) & 0xFF);
OCR3AL = (uint8_t)(pwm_freq & 0xFF);
}
#endif
#if AVR_PWM_USE_TIM4 || defined(__DOXYGEN__)
pwmObjectInit(&PWMD4);
PWMD4.channels = PWM_CHANNELS;
if (pwm_mode == FAST_MODE_FIX_FREQ) {
TCCR4A |= (1 << WGM41) | (1 << WGM40);
TCCR4B &= ~(0 << WGM43);
TCCR4B |= (1 << WGM42);
}
if (pwm_mode == FAST_MODE_VAR_FREQ) {
uint32_t pwm_freq;
pwm_freq = 0;
TCCR4A |= (1 << WGM41) | (1 << WGM40);
TCCR4B |= (1 << WGM43) | (1 << WGM42);
// Calcul and set the PWM4 frequency.
pwm_freq = 16000000/64;
// TODO: Replace 500 by PWMD4.period.
pwm_freq /= 500;
pwm_freq -= 1;
//OCR4AH = (uint8_t)((pwm_freq >> 8) & 0xFF);
//OCR4AL = (uint8_t)(pwm_freq & 0xFF);
OCR4AH = 0x01;
OCR4AL = 0xF3;
OCR4BH = 0x01;
OCR4BL = 0xF3;
OCR4CH = 0x01;
OCR4CL = 0xF3;
}
#endif
#if AVR_PWM_USE_TIM5 || defined(__DOXYGEN__)
pwmObjectInit(&PWMD5);
PWMD5.channels = PWM_CHANNELS;
TCCR5A = (1 << WGM51) | (1 << WGM50);
TCCR5B = (0 << WGM53) | (1 << WGM52);
#endif
}
Here is the code where the prescaler is set:
Code: Select all
void pwm_lld_start(PWMDriver *pwmp) {
uint16_t prescaler = 64;
if (pwmp->state == PWM_STOP) {
#if AVR_PWM_USE_TIM2 || defined(__DOXYGEN__)
if (pwmp == &PWMD2) {
TCCR2B &= ~((1 << CS22) | (1 << CS21));
TCCR2B |= (1 << CS20);
if (pwmp->config->callback != NULL)
TIMSK2 |= (1 << TOIE2);
return;
}
#endif
uint8_t i = timer_index(pwmp);
/* TODO: support other prescaler options */
// Added by NAFT.
/* Prescaler is 0, No clock source (Timer/counter stopped. */
if (prescaler == 0)
*regs_table[i].tccrb &= ~(1 << CS12) | ~(1 << CS11) | ~(1 << CS10);
/* Prescaler is 1, cock source is CLK. */
if (prescaler == 1) {
*regs_table[i].tccrb &= ~(1 << CS12) | ~(1 << CS11);
*regs_table[i].tccrb |= (1 << CS10);
}
/* Prescaler is 8, clock source is CLK/8 . */
if (prescaler == 8) {
*regs_table[i].tccrb &= ~(1 << CS12) | ~(1 << CS10);
*regs_table[i].tccrb |= (1 << CS11);
}
/* Prescaler is 64, clock source is CLK/64. */
if (prescaler == 64) {
*regs_table[i].tccrb &= ~(1 << CS12);
*regs_table[i].tccrb |= (1 << CS11)| (1 << CS10);
}
/* Prescaler is 256, clock source is CLK/256 .*/
if (prescaler == 256) {
*regs_table[i].tccrb &= ~(1 << CS11) | ~(1 << CS10);
*regs_table[i].tccrb |= (1 << CS12);
}
/* 1024 is prescaler, clock source is CLK/1024. */
if (prescaler == 1024) {
*regs_table[i].tccrb &= ~(1 << CS11);
*regs_table[i].tccrb |= (1 << CS12) | (1 << CS10);
}
// TODO: Add support for External clock source on Tn pin.
// Falling and rising edges.
if (pwmp->config->callback != NULL)
*regs_table[i].timsk = (1 << TOIE1);
}
}
Maybe I'm wrong some where
Thanks for your help