Week 9: Pulse Width Modulation

This week I decided to implement pulse width modulation (PWM) into the micro controller to control the motors speeds which would save on battery power as well as help me to get a better understanding of PWM and how to use it in the MSP430 chip but first we tried a code that would change the direction of the motors when the and object was within 30cm of the range finder, the code is shown below:

//
// RoboSlam Example: Rangefinder example
// Code is for MSP430G2452 or MSP430G2553
// Written by Ronan Byrne - Last updated 24-3-2015
//
// This version aims to reduce the effect of false
// negatives from the rangefinder.
//
  
#include <msp430.h>
  
// function prototype
int distance();
  
// main function
int main( void )
{
    // disable watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
  
    // configure digital inputs and outputs
    P1DIR = 0b01100001;   // Port 1 outputs: P1.6 (trig)
    P2DIR = 0b00110011;   // Port 2 outputs: P2.3 (LED), P2.4-5 (motor)
  
    int d;         // distance
    int dc = 0;    // distance counter
    int state = 1; // state variable
     
    // Main loop implements simple state machine
    while(1)
    {
        // Measure distance using rangfinder
        d = distance();
         
        // Update distance counter
        if (d < 30) dc = 10;          // positive reading sets dc to 10
        else if (dc > 0) dc = dc - 1; // negative reading reduces dc by 1
         
        if (state == 1)      // STATE 1: SPIN
        {
            // left motor reverse, right motor reverse
            P1OUT = 0b00000001;
            P2OUT = 0b00100010;
             
            // change state?
            if (dc > 0) state = 2;
        }
        else if (state == 2) // STATE 2: ATTACK
        {
            // left motor forward, right motor forward
            P1OUT = 0b00100000;
            P2OUT = 0b00010001;
             
            // change state?
            if (dc == 0) state = 1;
        }
    }
}
 
//
// This function measures distance in cm using the rangefinder.
// It assumes TRIG is P1.6 and ECHO is P1.7.
//
int distance()
{
    // Send 20us trigger pulse
    P1OUT |= BIT6;
    __delay_cycles(20);
    P1OUT &= ~BIT6;
      
    // Wait for start of echo pulse
    while((P1IN & BIT7) == 0);
      
    // Measure how long the pulse is
    int d = 0;
    while((P1IN & BIT7) > 0)
    {
        // The following delay was worked out by trial and error
        // so that d counts up in steps corresponding to 1cm
        __delay_cycles(30);
        d = d + 1;
        if (d >= 400) break;
    }
     
    // Leave 100ms for any ultrasound reflections to die away
    __delay_cycles(100000);
     
    // Pass the measured distance back to the calling function
    return d;
}

This code worked well most of the time but occasionally the motors would get into a switching fit where the motors would just switch forward and backward every second, even with the code to reduce the effect of false readings, the false readings caused a problem so in the bot we would need to depend less on the range sensor to find the bot and just run around the ring with a limit switch on the front and push forward when the switch is pressed.
Onto the PWM I started with a pre-written code that increased the voltage on an LED every second and reset at full voltage. For my code I would try increase the pulse width every time one of the input pins went high, this was done by just connecting the power rail to a grounded pin on the MPS430. I recorded the readings on an oscilloscope to see the duty cycle change but as I’ve tested and changed many codes I accidentally saved over this code but I have an updated version which changes pulse depending if there is anything in range of the range sensor, duty cycle increases when somethings in range and decreases when there’s not. The previous codes clock was only connected to the oscilloscope but this clock was connected to the power of the power chip and this meant being able to control the speeds of both motors, this code is shown below:

//
// Timer_A PWM example for MSP430G2553
//
// This program generates a 50Hz PWM signal on TA1.1 (pin 10).
// The duty cycle ramps up if an object is in range of range sensor
// and the opposite if nothing is there
// This is achieved simply by incrementing the value of TA1CCR1.
// The PWM period could also be changed by assigning a new value
// to TA1CCR0, but that isn't done here.
// 
// The pulse is is of TA1.1 is connected to the power of the power chip
// by doing this we can control the speeds of both motors 
// Written by Ronan Byrne - last updated 28-3-2015
//
  
#include <msp430.h>
#define FORWARD 0b00010001

// function prototype
int distance();

//int d; 
int main( void )
{
    int d;         // distance
    int dc = 0;    // distance counter
    int state = 1; // state variable
    
    
    // Watchdog timer
    WDTCTL = WDTPW + WDTHOLD; // Disable watchdog timer
     
    // Select primary peripheral module function on P2.2 (i.e. TA1.1)
    P2SEL  = 0b00000100;
    P2SEL2 = 0b00000000;
    P2DIR  = 0b00110111; // Pin must also be configured as an output
    P1DIR = 0b01000001;   // Port 1 outputs: P1.6 (trig)
    
     
    // Configure Timer A interrupt
    TA1CTL = TASSEL_2 + ID_0 + MC_1; // Timer_A1: SMCLK clock, input divider=1, "up" mode
    TA1CCR0 = 20000;                  // Set Timer_A1 period to 20ms for 50Hz PWM
    TA1CCR1 = 10000;                   // 50% duty cycle initially (10ms pulse width)
    TA1CCTL1 = OUTMOD_7;             // Select "Reset/Set" output mode
    
    P2OUT = FORWARD;                // Set Motors to forward to see effect of 
    // This loop is just an example of varying the PWM duty cycle on
    // TA1.1 simply by updating the value of TA1CCR1.
    while(1)
    {
        d=distance();
        if (d < 30) dc = 10;  
        else if (dc > 0) dc = dc - 1;
        
        if (dc > 0) // If Something in range increase voltage every second
        {
            TA1CCR1 += 1000;
            __delay_cycles(1000000);
        }
        else // Else decrease voltage every second
        {
            TA1CCR1 -= 1000;
            __delay_cycles(1000000);
        }
    }
     
    return 0;
}
int distance()
{
    // Send 20us trigger pulse
    P1OUT |= BIT6;
    __delay_cycles(20);
    P1OUT &= ~BIT6;
      
    // Wait for start of echo pulse
    while((P1IN & BIT7) == 0);
      
    // Measure how long the pulse is
    int d = 0;
    while((P1IN & BIT7) > 0)
    {
        // The following delay was worked out by trial and error
        // so that d counts up in steps corresponding to 1cm
        __delay_cycles(30);
        d = d + 1;
        if (d >= 400) break;
    }
     
    // Leave 100ms for any ultrasound reflections to die away
    __delay_cycles(100000);
     
    // Pass the measured distance back to the calling function
    return d;
}

I connected the oscilloscope to the motors and got the following signals at half and full duty cycle:
Half Duty Cycle

Full Duty Cycle
The voltage was at two volts/box and 5ms/box being powered by a 7volts, drained 9 volt battery, at half duty cycle the voltage was 6.4V and 7V at full but when when powered with the full 9V its 7V to 8.2V which isn’t as big a differance I would’ve thought but it would still save some battery. The reason we can’t the full 9V on the motor is because there is still some internal components for voltage to drop across between the output and ground. Also you can see that there is some noise produced from the motors which is expected and that’s what the capacitors on the power rail is for, to filter out this noise so it doesn’t cause any chaos with the controller. I could’ve had two pins doing PWM but I think one will do and we will half enough things for the chip to process so only having one will save on processing time and one less thing to go wrong. That was all for that week, we still didnt have any arts to work with so the only things that could be done was code and circuitry and next week I would make a start on the fight code.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s