PWM generation Topic is solved

ChibiOS public support forum for topics related to the Atmel AVR family of micro-controllers.

Moderators: utzig, tfAteba

User avatar
tfAteba
Posts: 526
Joined: Fri Oct 16, 2015 11:03 pm
Location: Chartres, France
Has thanked: 80 times
Been thanked: 46 times

PWM generation

Postby tfAteba » Wed Nov 23, 2016 11:26 pm

Hi all,

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 :)
regards,

Theo.

User avatar
tfAteba
Posts: 526
Joined: Fri Oct 16, 2015 11:03 pm
Location: Chartres, France
Has thanked: 80 times
Been thanked: 46 times

Re: PWM generation

Postby tfAteba » Thu Nov 24, 2016 7:13 pm

Hello all,

Problem solved after a few hours of tracking :D

I Will make my modification available after more tests. May be it will help another people.

For now, PWM generation works fine.

Thanks for your attention and help!
regards,

Theo.

User avatar
igor
Posts: 50
Joined: Sun Aug 16, 2015 7:24 pm
Location: Helsinki, Finland
Has thanked: 1 time

Re: PWM generation

Postby igor » Sun Nov 27, 2016 10:28 pm

Hi,
It looks like we are doing something similar, only on slightly different platforms.
Is there any specific reason why you are using the 2560?
The footprint is huge, for my use case.
With one Mini Pro, I can drive 4 wheels independently and also get the tacho feedback.
Would that be enough for you?

BTW, I've also written an interrupt based I2C slave driver, to handle messaging, plus a crude python UI to control it from a PC.
In my design I'm using an Intel Edison as master, but I'm planning to swap it out in favor of a C.H.I.P. board: it's only $9 and should do the job.

User avatar
tfAteba
Posts: 526
Joined: Fri Oct 16, 2015 11:03 pm
Location: Chartres, France
Has thanked: 80 times
Been thanked: 46 times

Re: PWM generation

Postby tfAteba » Sun Nov 27, 2016 11:24 pm

Hi Igor,

Is there any specific reason why you are using the 2560?

I'm using the 2560 because, I made a first version of the software of the robot long time ago. With the Arduino IDE, so all board with 328 MCU wasn't adapted for my project project because of the Arduino IDE restriction on the interrupts pin. Only two where available. But I was needed four. That was the main reason why I did use the mega board.

The footprint is huge, for my use case.

For my use case, it is not a problem :)

Would that be enough for you?

An Arduino Micro can effectively be enough but my design it already made. May be it could be an future improvement for my robot :). But I also plan to add some sensors to the robot so have many i/o ports can be useful.

BTW, I've also written an interrupt based I2C slave driver, to handle messaging, plus a crude python UI to control it from a PC.
In my design I'm using an Intel Edison as master, but I'm planning to swap it out in favor of a C.H.I.P. board: it's only $9 and should do the job.

Nice job, really cool. I also plan to do some thing like that, but it is not really my priority now.
I want to make a port of the firmware under ChibiOS for now but a lot of trouble.
I hope I will manage and succeed all of that to share a video :).
regards,

Theo.

User avatar
tfAteba
Posts: 526
Joined: Fri Oct 16, 2015 11:03 pm
Location: Chartres, France
Has thanked: 80 times
Been thanked: 46 times

Re: PWM generation  Topic is solved

Postby tfAteba » Tue Dec 06, 2016 11:36 pm

Hi all,

After resolving the PWM problem for motor driving, I finilly finish the robot program :D

As promized, here is the link to a small video of the robot in action.
viewtopic.php?f=8&t=3721
regards,

Theo.


Return to “AVR Support”

Who is online

Users browsing this forum: No registered users and 1 guest