Tank Robot Sr. Design - PWM questions

Introduction
I am working on a Mechanical Engineering senior design project building a 40lb tank robot driven by a wireless PS2 controller. Following is a basic schematic of the control plan:

The microcontroller is an Arduino Uno.

The motor contollers are Cytron 10A, 3-25V Single DC Motor Controller (http://www.robotshop.com/ca/cytron-single-dc-motor-controller-2.html)

The motors are standard OEM windshield wiper motors (Monster Guts - Your Wiper Motor / Pneumatics Headquarters!)

The battery is an AGM motorcycle battery (12V, 18AH).

Questions
For Arduino, the base frequency for pins 3, 9, 10, and 11 is [corrected] 490.196078 Hz. The base frequency for pins 5 and 6 is [corrected] 976.5625 Hz. The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64, 256, and 1024. The divisors available on pins 3 and 11 are: 1, 8, 32, 64,128, 256, and 1024. (Arduino Playground - PwmFrequency)

"The Cytron motor controllers is capable of "speed control PWM frequency up to 10KHz" and "supports both locked-antiphase and sign-magnitude PWM operation."

I need to know:

  1. What effect will there be if I output 31250 Hz or 62500 Hz from the Arduino to the Cytron? Will there be overheating or just dropping signals/signal distortion?

  2. What effect will there be (on the signal, power usage, etc) of using lower PWM frequencies such as 31250/8 = 3906.25 Hz?

  3. What will the effect be on motor performance? Is there tabulated data about the resistance and inductance of these common motors?

  4. How do I use locked-antiphase versus sign-magnitude PWM operation using Arduino?

Thank you for your help. Hopefully the answers to these questions don't just make new questions!

John

For Arduino, the base frequency for pins 3, 9, 10, and 11 is 31250 Hz.

No, it isn't. The default frequency for those pins is ~488 Hz.

The base frequency for pins 5 and 6 is 62500 Hz.

Nope. ~976 Hz.

I was citing www.arduino.cc/playground/Code/PwmFrequency is it just plain wrong? Could you please explain? How would a 10KHz switching frequency be attained?

jdeck004:
I was citing www.arduino.cc/playground/Code/PwmFrequency is it just plain wrong?

It is certainly possible I made a mistake so let's take a look at the source code. The code that initializes PWM is in "wiring.c"; specifically the "init" function.

  sbi(TCCR0A, WGM01);
  sbi(TCCR0A, WGM00);

...sets timer 0 to "Fast PWM".

  sbi(TCCR0B, CS01);
  sbi(TCCR0B, CS00);

...sets the prescaler to 64.

The frequency is fOCnxPWM = fclk_I/O / ( N ? 256 ) = 16000000 / ( 64 * 256 ) = 976.5625 Hz.

  sbi(TCCR1B, CS11);
  sbi(TCCR1B, CS10);

...sets the prescaler to 64.

  sbi(TCCR1A, WGM10);

...sets timer 1 to "PWM, Phase Correct, 8-bit".

The frequency is fOCnxPCPWM = fclk_I/O / ( 2 ? N ? TOP ) = 16000000 / ( 2 * 64 * 255 ) = 490.196078 Hz.

The answer is "yes". The "base frequency" listed on that page is wrong.

How would a 10KHz switching frequency be attained?

Thank you. I see that you are configuring pins 9 and 10. I have 3 motor outputs total. Can the Arduino Uno be configured to work for 3 simultaneous PWM outputs? The most important aspect for me is getting power to the wheels. What effect will the switching frequency have on the power output?

jdeck004:
Thank you

You are welcome.

Can the Arduino Uno be configured to work for 3 simultaneous PWM outputs?

The Uno can provide up to six simultaneous PWM outputs. The four outputs associated with timer 1 and timer 2 can be configured any way you wish. Any changes to he two outputs associated with timer 0 will effect millis / micros / delay / delayMicroseconds; I suggest leaving timer 0 alone.

What effect will the switching frequency have on the power output?

I have no idea. Someone else will have to help with that question.

Ok thanks again hopefully someone else chimes in as well.

If I modify only timer1 how many fast switching outputs will be available?

Thanks

jdeck004:
If I modify only timer1 how many fast switching outputs will be available?

Two. There are two outputs associated with each timer.

Will the program you posted modify both timer1 and timer2 so that I can achieve fast switching on 3 pins? Could you briefly explain what it does? If not, could you direct me how to achieve this result?

Unfortunately my programming experience is only in MATLAB.

Thanks,
John

jdeck004:
Will the program you posted modify both timer1 and timer2 so that I can achieve fast switching on 3 pins?

The usable code...

...only modifies timer 1.

Could you briefly explain what it does?

The code changes timer 1 to mode 14 (one of the "fast" modes; details in the datasheet), sets output A to normal, and sets output B to inverted. If you want both outputs to be normal, make this change...

// Set Compare Output Mode and part of the Waveform Generation Mode (mode 14)
TCCR1A =
(1 << COM1A1) | (0 << COM1A0) // Clear OC1A on Compare Match, set OC1A at BOTTOM (non-inverting mode)
|
(1 << COM1B1) | (0 << COM1B0) // Clear OC1B on Compare Match, set OC1B at BOTTOM (non-inverting mode)
|
(1 << WGM11) | (0 << WGM10); // Mode 14: Fast PWM, TOP = ICR1, Update of OCR1x at BOTTOM, TOV1 Flag Set on TOP

The value is 0 through 199 for both outputs. These lines of code change the output (for non-inverting)...

  // Full on
  OCR1A = 199;
  OCR1B = 199;

  // Full off
  OCR1A = 0;
  OCR1B = 0;

  // Half
  OCR1A = 99;
  OCR1B = 99;

If not, could you direct me how to achieve this result?

The big steps for changing timer 2 are identical. The details (bit values) are different. I suggest copying the code in setup and then working through it line-by-line checking the datasheet as you go. If you get stuck, I suspect you'll find help here.

I am clearly in over my head here. What is the function of this section? Is it merely a test?

void loop( void )
{
  delay( 1000 );

  // A full on
  OCR1A = 199;

  delay( 1000 );
  
  // B full on
  OCR1B = 0;

  delay( 1000 );

  // A twinkling
  OCR1A = 1;

  delay( 1000 );

  // B twinkling
  OCR1B = 198;

  delay( 1000 );

  // A off
  OCR1A = 0;

  delay( 1000 );

  // B off
  OCR1B = 199;
}

When you reference the datasheet, does that mean the datasheet for the atmega328p?

Keep in mind I don't know this programming language at all and have no experience with using datasheets.

Hope you don't mind spoonfeeding a little bit. Thanks again for your help.

John

Is it merely a test?

Yes. It is meant to exercise the two output pins attached to timer 1 and to illustrate how to set the output value. Normally, PWM values range from 0 to 255. To achieve 10 KHz output, the range is reduced. The new range is from 0 to 199.

Note: Timer 1 is a 16 bit timer so it should be possible to extend the range beyond 0 to 199 (and beyond 0 to 255). @Arman did not seem interested so I didn't bother.

jdeck004:
What is the function of this section?

Every Sketch must have two functions: setup and loop. setup is called first and only once. In most cases, setup is used to prepare the hardware. loop is called second and forever after. loop is typically where the action is; in your case where robot behaviour code goes.

So, this function is called over and over (some comments added to hopefully add clarity)...

void loop( void )
{
  delay( 1000 );  // Pauses execution for 1000 milliseconds

  // A full on
  OCR1A = 199;  // Sets the timer 1 channel A "Output Compare Register" to 199.  The earlier code configured timer 1 to generate "fast PWM" signals and enabled output on the OC1A pin so this assignment changes the pulse width.

  delay( 1000 );  // Another 1 second pause
  
  // B full on
  OCR1B = 0;  // Sets the timer 1 channel B "Output Compare Register" to 0.  This channel was configured for inverted output so zero is full on.

  delay( 1000 );  // 1 second

  // A twinkling
  OCR1A = 1;  // Sets timer 1 channel A output to the smallest possible pulse width (1 / 200 or just barely on).

  delay( 1000 );

  // B twinkling
  OCR1B = 198;  // Because channel B is inverted, this sets the smallest possible pulse width ((199-198)/200 or just barely on).

  delay( 1000 );

  // A off
  OCR1A = 0;

  delay( 1000 );

  // B off
  OCR1B = 199;
}

When you reference the datasheet, does that mean the datasheet for the atmega328p?

Yes.

Keep in mind I don't know this programming language at all

Fortunately, you have LOTS of working examples and there seem to be helpful folks here.

and have no experience with using datasheets

The Atmel + AVR GCC folks did a great job of binding the programming language to the datasheet. For example, this line of code sets the value of the OCR1A register...

OCR1A = 0;

Search the datasheet for "OCR1A" and you will learn everything you need to know (and probably some things you don't care to know ;)) about the OCR1A register. Need to assign a value to the DIDR1 register? No sweat. It's just like assigning a value to a variable...

DIDR1 = 0;

Thanks again for your help.

You are welcome.

The resolution from 0 to 199 seems fine for my purpose as well.

void setup( void )
{
  // Turn off the timer while we make changes
  TCCR2B = TCCR2B & ~ ((1 << CS22) | (1 << CS21) | (1 << CS20));
  
  // Ensure the Timer 2 output pins are configured for output
  pinMode( ???, OUTPUT );
  pinMode( ????, OUTPUT );
  
  // Set Compare Output Mode and part of the Waveform Generation Mode (mode 14)
  TCCR2A = 
      (1 << COM2A1) | (0 << COM2A0)  
      |
      (1 << COM2B1) | (0 << COM2B0)  
      
      (1 << WGM21) | (0 << WGM20);  
      
  // Set the other half of the Waveform Generation Mode (mode 14) and ensure a few things are disabled
  TCCR2B =
      (0 << FOC2A)  
      |
      (0 << FOC2B)  
      |
      (1 << WGM23) | (1 << WGM22) 
      |
      (0 << CS22) | (0 << CS21) | (0 << CS20);  


  ICR2 = 199;
  
  // Start with both outputs turned off
  OCR2A = 0;
  OCR2B = 0;
  
  // Start the clock
  TCCR2B = 
      TCCR2B 
      |
      (0 << CS22) | (1 << CS21) | (0 << CS20);  
}

How does this look? According to the register summary many of the bits transfer over directly by changing n=1 to n=2.

I was not able to determine which output pins timer2 controls.

jdeck004:
I was not able to determine which output pins timer2 controls.

How to decode the OCnx pin identifier ... Timer / Counter n Output Compare Match x Output ... the number (n) indicates which timer ... the letter (x) indicates which channel. So, we need to search the datasheet for "OC2A" (Output Compare for Timer 2 Channel A) and "OC2B" (Output Compare for Timer 2 Channel B)...

Open the datasheet. Navigate to "Pin Configurations". Search for "OC2A" and "OC2B".

How does this look?

I'll try to look at it this evening.

Looks like OC2a leads into Pin 17, or PB3, of the PDIP. OC2b leads to Pin 5, or PD3, of the PDIP.

It looks like PB3 means Port B pin 3, and PD3 is Port D pin 3.

I still cannot find documentation in the datasheet about what pins lead to these. I think this is because the datasheet is not specific to the Arduino Uno.

Looking up the Arduino Uno schematic it looks like PD3 leads to either pin 3, and PB3 leads to pin 11.

The same schematic leads me to see that OC1a and OC1b lead to pins 9 and 10 respectively, which appears to verify my conclusion.

How does this look?

I'll try to look at it this evening.

Ok. I will be checking back here often. I am quite sure it will need help.

John

I still cannot find documentation in the datasheet about what pins lead to these. I think this is because the datasheet is not specific to the Arduino Uno.

This should help (the labels / assignments are the same for the 328 processor)...

According to the register summary many of the bits transfer over directly by changing n=1 to n=2.

That is certainly true but timer 2 does not have a mode 14. To get 10 KHz output it is necessary to set the prescaler and the TOP value. That means you will have to use mode 7. That also means that OCR2A is used to set the TOP value and you will have to give up one output (OC2A).

I think this will work...

void setup( void )
{
  // Turn off the timer while we make changes
  TCCR2B = TCCR2B & ~ ((1 << CS22) | (1 << CS21) | (1 << CS20));
  
  // Ensure the Timer 2 output pin is configured for output
  pinMode( 3, OUTPUT );
  
  // Set Compare Output Mode and part of the Waveform Generation Mode (mode 7)
  TCCR2A = 
      (0 << COM2A1) | (0 << COM2A0)  
      |
      (1 << COM2B1) | (0 << COM2B0)  
      |
      (1 << WGM21) | (1 << WGM20);  

  // Set the other half of the Waveform Generation Mode (mode 7) and ensure a few things are disabled
  TCCR2B =
      (0 << FOC2A)  
      |
      (0 << FOC2B)  
      |
      (1 << WGM22) 
      |
      (0 << CS22) | (0 << CS21) | (0 << CS20);  


  OCR2A = 199;

  // Start with the output turned off
  OCR2B = 0;
  
  // Start the clock
  TCCR2B = 
      TCCR2B 
      |
      (0 << CS22) | (1 << CS21) | (0 << CS20);  
}

That is a handy reference. I was able to infer the timer1 and timer2 pins but this will be much faster in the future.

I haven't had a chance to test out that code yet. Before I can, I have a basic question about implementation.

I have a PS2 controller interface library from Bill Porter, and I am writing a motor control program to output phase-correct PWM to a motor driver. I know that I can use #include ps2x.h to include the library of commands for the controller. Where do these timer modifier codes go? In the setup section of my motor control program? Or are they 'called' in a similar way to the ps2x library? If you need me to provide what I have written, I can.

Also, do all of the libraries upload to the arduino when I upload a program? If not how are they employed?

Thank you.

jdeck004:
I have a PS2 controller interface library from Bill Porter, and I am writing a motor control program to output phase-correct PWM to a motor driver.

Will that be part of the project you described above?

Where do these timer modifier codes go? In the setup section of my motor control program?

In setup. But you will not be able to use the stuff above with the PS2 controller interface library. There are three timers on an Arduino Uno. Timer 0 is used by millis (and two PWM pins). It should be left alone.

The stuff above modifies timer 1 and timer 2 to generate a 10 KHz fast PWM signal on up to three pins. The PS2 controller interface library is also going to use a timer (either 1 or 2). You've run out of timers.

Or are they 'called' in a similar way to the ps2x library?

Not in their current form. The code could be turned into a library but I recommend including it directly in your Sketch at least until you've tested it.

Also, do all of the libraries upload to the arduino when I upload a program?

No. First, there has to be a reference to the library. That's what the "#include" lines do. Then, your Sketch has to actually use the library.

Basically, only the stuff used in your Sketch gets uploaded.