PWM with MCU's

Discussion in 'Embedded Systems and Microcontrollers' started by Shagas, Jul 17, 2013.

  1. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
    Hello ,

    I'm a beginner to Microcontrollers .
    I've chosen Atmel AVR and i've been playing with them for a few days now.
    Currently using the atmega48

    Question #1 :

    Why are there special 'modes' for PWM ? Why do I have to activate some 'fast pwm' registers or 'waveform generation mode' or those things ?

    Is it not practical to just assign whatever output (PORTB for example) and use PWM using _delay_ms() ?
    Edit: Or does "PWM Mode" make things simpler in a way ?


    Also , what is meant by a 10 bit PWM ? I'm assuming that it means a duty cycle resolution of about 0.1% hmm?

    Thanks in advance for the answers
     
  2. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    Sure you can implement PWM with output to a port and time delays.
    But what happens when your code has to do something in between outputs?
    Your PWM timing is going to get messed up and will not be very stable.

    That is what PWM timer modes are for. The timer hardware takes care of generating consistent and stable time delays while the code can go off and do something else.

    10-bit PWM means that the timer register is 10 bits wide. It can count from 0 to 1023.
    Yes, that means that your PWM signal can be adjusted to a resolution of 0.1%.
     
  3. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
    Okay , makes sense.

    So while i'm running other code my timer independantly generates PWM . But i'm assuming that the timer itself generates a fixed PWM for example say 50% duty cycle at 1khz. So if I want to change that I have to wait until the micro finishes executing whatever other stuff it's doing , and then update the PWM by sending data to the PWM hardware
    am I right?

    Thanks for the answer MRchips
     
  4. Papabravo

    Expert

    Feb 24, 2006
    10,144
    1,791
    No wrong. You can start, stop, and update the registers at any time. The results will be appropriate to the situation. If you want to change things in an organized, instead of a random way, then you can arrange to do things when certain conditions are all true.
     
    Shagas likes this.
  5. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    A properly designed mcu based control system would be interrupt driven. That is, internal or external input can interrupt the normal flow of program code and the PWM registers can be updated instantly.

    For example, a robotic arm may employ a DC servo motor driven by a PWM signal. The mcu controller would have to update the PWM register continuously on the fly in order to effect smooth motion, at the same time while taking care of other tasks.
     
  6. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
    So basically , lets say I want to update my pwm every 10 counts of the timer , then I would set up the timer to interrupt the MCU , stopping whatever it's doing , update the registers , and then continue the code until the next interrupt?
     
  7. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    That's all there is to it.

    Also, since the PWM is already periodic, you can use the PWM register to interrupt on the start of every cycle.
     
    Shagas likes this.
  8. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
    Ok thanks , I think I am beginning to understand one of the 20 things that I don't understand in Microcontrollers :)
     
  9. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    One down, 19 to go. Fire away.
     
  10. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
    Well my next question is a bunch of code that is giving me 6 errors upon attempt to compile. Basically it's a 'nightrider' (or whatever the internet calls it nowadays) thingy which flashed LEDs from LED0 to LED7 and then back in a sequential order . The only modification is that I have 2 buttons which manually change the direction of flashing .

    There is a left button and a right button . If the pattern is progressing to the right and I press the left button , then it changes direction to the left starting from the led that was active when I pressed the button . If I press the right button while it's travelling right then nothing happens .
    Vice versa for the other side.

    Code ( (Unknown Language)):
    1.  
    2. #include <avr/io.h>
    3. #include <util/delay.h>
    4.  
    5. int x=0;
    6. int y=0;
    7.  
    8. int roamleft(int x);
    9. int roamright(int y);
    10.  
    11.  
    12. DDRB = 0b11111111;
    13. DDRD = 0b00000011;
    14.  
    15. PORTD = 1<<PIND2 | 1<< PIND3;
    16.    
    17.  
    18.  
    19. int main(void)
    20. {
    21.    
    22.    
    23.  
    24.    
    25.     while(1)
    26.     {
    27.    
    28.         x = roamright(y); // flash to the right  sequentially from LED Y to LED 7
    29.         y = roamleft(x);  // flash  to the left   sequentially from LED X to LED 0
    30.                
    31.     }
    32.    
    33.        
    34. }
    35.  
    36. int roamright(y)
    37. {
    38.     for(x=y;x<8;x++)    // cycles through the LED ports
    39.     {
    40.     PORTB = 1 << x;     // Flash the led
    41.     _delay_ms(100);     // delay before flashing next led
    42.     PORTB = 0;          // Turn LED port off
    43.     if(bit_is_clear(PIND,2))   // Test if button pressed
    44.     {
    45.         return x;             //break the cycle and call 'roamleft' carrying in the value that the led stopped at.
    46.     }
    47.    
    48.     }
    49.    
    50.     return x;                 // if button is not pressed , then x=7 will be carried into 'roamleft' so it starts to flash to the left sequentially starting from LED 7
    51.    
    52.        
    53.        
    54. }
    55.  
    56. int  roamleft(x)
    57.     {
    58.        
    59.  
    60.     for(y=x;y>=0;y--)
    61.    
    62.     {
    63.        
    64.     PORTB = 1 << y;
    65.     _delay_ms(100);
    66.     PORTB = 0;
    67.    
    68.     if(bit_is_clear(PIND,3))
    69.     {
    70.         return y;
    71.     }
    72.    
    73.    
    74.     }
    75.      return y;
    76.    
    77. }
    78.  
    79.  
    Can someone just skim through that and tell me if there are any coarse syntax errors or whatever that cannot be done the way I did it , i'd appreciate it.
    I'm using Atmel studio 6. It tells me I have 6 errors but It doesn't show me where they are.
    Thanks in advance

    Edit:
    I've had some experience in C++ and java in the past but some things confuse me here.
    Why do I see functions declared in some tutorials and others just omit it? Does it depend on the compiler or something?
     
    Last edited: Jul 17, 2013
  11. Shagas

    Thread Starter Active Member

    May 13, 2013
    802
    74
Loading...