This tutorial covers the details of Turning A Servo on the Kinetis K40 using TWR-K40x256-KIT evaluation board. Overview In this exercise you will build a “bare metal” (no RTOS) application which turns a servo, targeting a Freescale K40 board. You will: Create the Servo code in CodeWarrior Build the Servo project Download and run the code on a Kinetis K40 Tower System board Learn how to utilize the FlexTimer module to control a Servo To successfully complete this exercise you need the following board and development environment. The K40 Tower card, TWR-K40x256 Tower Elevator Panels Servo Prototyping Board Power to your servo - either utilize the 7.2v Nicad Battery or a DC power supply CodeWarrior for Microcontrollers 1. Hardware 2. Create a New CodeWarrior Project 3. Build the Code 4. Download/Debug/Run 5. Learning Step: Servo Code Description Example Code Variables Init_PWM_Servo PWM_Servo PWM_Servo_Angle Set Up a Look-Up Table for Servo Angles Other K40 Tutorials: Links 1. Hardware The first step of this tutorial requires you read the Turn A Servo article for background information on servo's, timer modules, PWM signals and counters. You will need to connect your servo to the microcontroller and also to a separate power source. 2. Create a New CodeWarrior Project The next step is to create a new project (or add this code to an existing project). 3. Build the Code If you have more than one project in your project view, make sure the proper project is the focus. The most reliable way to do this is to right click the project and choose Build Project as shown below. You can also go to the Project menu and choose the same command. If you encounter errors, look in the Problems view and resolve them. You can ignore any warnings. 4. Download/Debug/Run This link shows a video of the servo turning the wheels from left to right in small increments http://www.youtube.com/watch?v=QgwASk9DHvU&feature=relmfu 5. Learning Step: Servo Code Description Your code will sweep your servo from max to minimum angular position, and then back again continuously. Example Code This code sets up the Pulse Width Modulation Timer Module for use by a servo. It is set to utilize Edge-Aligned PWM, and this file properly configures the period, and pulse width for use by the other modules Several important functions are contained in this file: 1. Init_PWM_Servo () - initializes the timer module 2. PWM_Servo (double duty_Cycle) - enter the desired duty cycle setting for the servo 3. PWM_Servo_Angle (int Angle) - enter the desired angle for the servo Straight forward - PWM_Servo_Angle (45) Full left - PWM_Servo_Angle (90)Full right - PWM_Servo_Angle (0) 4. Servo_Tick - interrupt routine which executes once/servo period PWM_Servo (double duty_Cycle) Init_PWM_Servo () PWM_Servo_Angle (float Angle) void ServoTick() Variables FTM0_CLK_PRESCALE TM0_OVERFLOW_FREQUENCY Pulse_Width_Low Pulse_Width_High Total_Count Low_Count Scale_Factor Angle Init_PWM_Servo Void Init_PWM_Servo () { //Enable the Clock to the FTM0 Module SIM_SCGC6 |= SIM_SCGC6_FTM0_MASK; //Pin control Register (MUX allowing user to route the desired signal to the pin. PORTC_PCR4 = PORT_PCR_MUX(4) | PORT_PCR_DSE_MASK; //FTM0_MODE[WPDIS] = 1; //Disable Write Protection - enables changes to QUADEN, DECAPEN, etc. FTM0_MODE |= FTM_MODE_WPDIS_MASK; //FTMEN is bit 0, need to set to zero so DECAPEN can be set to 0 FTM0_MODE &= ~1; //Set Edge Aligned PWM FTM0_QDCTRL &=~FTM_QDCTRL_QUADEN_MASK; //QUADEN is Bit 1, Set Quadrature Decoder Mode (QUADEN) Enable to 0, (disabled) // Also need to setup the FTM0C0SC channel control register FTM0_CNT = 0x0; //FTM Counter Value - reset counter to zero FTM0_MOD = (PERIPHERAL_BUS_CLOCK/(1<<FTM0_CLK_PRESCALE))/FTM0_OVERFLOW_FREQUENCY ; // Count value of full duty cycle FTM0_CNTIN = 0; //Set the Counter Initial Value to 0 // FTMx_CnSC - contains the channel-interrupt status flag control bits FTM0_C3SC |= FTM_CnSC_ELSB_MASK; //Edge or level select FTM0_C3SC &= ~FTM_CnSC_ELSA_MASK; //Edge or level Select FTM0_C3SC |= FTM_CnSC_MSB_MASK; //Channel Mode select //Edit registers when no clock is fed to timer so the MOD value, gets pushed in immediately FTM0_SC = 0; //Make sure its Off! //FTMx_CnV contains the captured FTM counter value, this value determines the pulse width FTM0_C3V = FTM0_MOD; //Status and Control bits FTM0_SC = FTM_SC_CLKS(1); // Selects Clock source to be "system clock" or (01) //sets pre-scale value see details below FTM0_SC |= FTM_SC_PS(FTM0_CLK_PRESCALE); /******begin FTM_SC_PS details **************************** * Sets the Prescale value for the Flex Timer Module which divides the * Peripheral bus clock -> 48Mhz by the set amount * Peripheral bus clock set up in clock.h * * The value of the prescaler is selected by the PS[2:0] bits. * (FTMx_SC field bits 0-2 are Prescale bits - set above in FTM_SC Setting) * * 000 - 0 - No divide * 001 - 1 - Divide by 2 * 010 - 2 - Divide by 4 * 011 - 3 - Divide by 8 * 100 - 4 - Divide by 16 * 101 - 5 - Divide by 32 * 110 - 6 - Divide by 64 - * 111 - 7 - Divide by 128 * ******end FTM_SC_PS details*****************************/ // Interrupts FTM0_SC |= FTM_SC_TOIE_MASK; //Enable the interrupt mask. timer overflow interrupt.. enables interrupt signal to come out of the module itself... (have to enable 2x, one in the peripheral and once in the NVIC enable_irq(62); // Set NVIC location, but you still have to change/check NVIC file sysinit.c under Project Settings Folder } PWM_Servo Void PWM_Servo (double duty_Cycle) { FTM0_C3V = FTM0_MOD*(duty_Cycle*.01); } PWM_Servo_Angle
//PWM_Servo_Angle is an integer value between 0 and 90
//where 0 sets servo to full right, 45 sets servo to middle, 90 sets servo to full left
void PWM_Servo_Angle (float Angle)
{
High_Count = FTM0_MOD*(Pulse_Width_High)*FTM0_OVERFLOW_FREQUENCY;
Low_Count = FTM0_MOD*(Pulse_Width_Low)*FTM0_OVERFLOW_FREQUENCY;
Total_Count = High_Count - Low_Count;
Scale_Factor = High_Count -Total_Count*(Angle/90);
FTM0_C3V = Scale_Factor; //sets count to scaled value based on above calculations
}
Set Up a Look-Up Table for Servo Angles
int main(void)
{
//Servo angles can be stored in a look-up table for steering the car.
float table[n] = { steering_angle_0;
steering_angle_1;
steering_angle_2;
……
steering_angle_n-1
};
Steering_Angle = table[x];
PWM_Servo_Angle (Steering_Angle); // Call PWM_Servo_Angle function.
}
Other K40 Tutorials: K40 Blink LED Tutorial K40 DC Motor Tutorial Kinetis K40: Turning A Servo K40 Line Scan Camera Tutorial Links Kinetis K40 TWR-K40X256-KIT
View full article