a.k.a. Lab 4
1. Supplies
You will need the following items for this project:
-
LaunchPad devboard
-
EN12
rotary incremental encoder -
SG90
servo -
Analog Discovery 2, or another oscilloscope to measure wave forms.
-
Paper notepad for taking notes and working out calculations.
2. Specifications
Turn your encoder’s shaft and the servo rotates in the same direction until it reaches the end of its travel. Turning the encoder in the same direction after the servo reaches its travel limit has no effect. Changing the direction of the encoder immediately causes the servo to rotate in the other direction.
Rotating the encoder 180° causes the servo to also move over an angle of 180°.
Each press of a button on the LaunchPad causes the servo to move the same amount as a detent increment of the encoder (15° encoder rotation).
2.1. Requirements
The first set of requirements should be accomplished by the end of the lab session:
-
The servo PWM waveform must be generated completely in the timer hardware.
-
Pressing SW1 shall move the servo 7.5° CCW.
-
Pressing SW2 shall move the servo 7.5° CW.
Then also make the encoder control the servo position:
-
The servo shall rotate the same amount and direction as the encoder shaft.
Finally,
-
Holding SW1 for at least 500ms shall move the servo to the CCW end stop.
-
Holding SW2 for at least 500ms shall move the servo to the CW end stop.
-
Holding SW1 and SW2 for at least 500ms shall move the servo to the middle of its range.
3. Design sequence
A structured approach to figuring everything out is wise. Here is some information and an example ordering that works on the functional units separately first.
Open your notebook and prepare your favourite writing instrument to make notes |
3.1. Button inputs
Review reading the buttons' state as inputs. Demonstrate successfully reading a button by changing an LED in response to a button push.
Always do a "blinky" before proceeding!
3.2. PWM with TimerA to a pin
This aspect continues from Monday’s day19 class time discussion about PWM and TimerA.
Remember and research the TimerA hardware behavior in the Family User Guide. Figure 25-1 on page 644 is especially useful.
Determine the appropriate
-
clock source (use SMCLK: use the LaunchPad user guide to find the default frequency)
-
counting mode (§ 25.2.3)
-
output mode (§ 25.2.5) for a PWM signal that starts at
1
then changes to0
when the timer reaches the correspondingTA0CCRx
value.
Registers:
-
TA0CTL
-
TA0CCR0
-
TA0CCRx
andTA0CCTLx
for the appropriatex
(you’ll figure outx
in the next segment)
We wish to connect an OUTx
signal (Figure 25-1) to a physical pin as an output signal.
This requires a few configuration bits to setup from the DIgital I/O peripheral section, §25.
The first task is to determine exactly what port+pin connects to what peripheral function.
This information is contained in the datasheet for the specifc device we have on the LaunchPad, file MSP430FT6989-datasheet.pdf
Check datasheet §6.11.11: Detailed Specifications -> Peripherals -> Timer_A TA0.
Table 6-12 shows that module blocks CCR1 and CCR2 are available for external connections.
(Remember that we are using CCR0 to generate the entire period.)
This module output signal TA1
and is mapped to device output signal TA0.1
and can be attached to (one or more of) port pins P1.0, P1.6, P7.2, P7.6, or to the internal analog-to-digital converter peripheral.
P1.0 is the LED1 on the LaunchPad, so maybe not use that pin. P1.6 is the only other port pin that is available on a convenient header pin.
Notice that if you wanted to use P1.7, you also need to use CCR2.
-> How to connect P1.6 to the timer peripheral??
Go back to the datasheet section §6.11.24 Input/Output Diagrams. Find the specific section + table that applies to P1.6.
Read this table from left to right and see that this table tells you exactly which bits in which registers to set to route this signal to the external pin. (P1DIR, P1SEL1, and P1SEL0 registers)
Verify that you understand the timer setup and that the output pin has the correct period (20ms) and pulse length (1—2ms) by measuring with an oscilloscope.
Connect a servo and verify that it rotates to the correct position when sent a signal from the LaunchPad. Change the code and re-download to demonstrate that the servo moves to a different position.
3.3. Buttons change pulse length
Write code that changes the TA0CCRx
value in appropriate increments for each button press.
Don’t forget to handle what happens when the servo is at the ends of its travel!
Use an oscilloscope to watch the pulse width change when you press the two buttons.
Hook up the servo and have a minute of fun making the servo move!
3.4. Refactor your code
Create a few functions to hold the main functions (lol) of your code so that your main()
doesn’t require you to scroll to see the whole thing.
Perhaps create a initBoard()
, initTimers()
, and readButtons()
functions.
Or something else that makes your code read closer to an English description of what it does.
Verify that your system behaves exactly the same after this refactoring!
3.5. Read the encoder
Make a few sketches of how you will connect the encoder to your LaunchPad. Talk this over with your partner so you can settle on the details.
-
How do you read multiple inputs (encoder A and B) at once?
-
How do you determine the rotation direction and "distance"?
This requires on-paper work and thinking.
-
If you can’t clearly describe to someone your strategy for reading the encoder, then do not attempt to write any code yet!
4. Resources
Files mentioned below are all in the GDrive folder: docs/TI-LaunchPad-FR6989
4.3. LaunchPad hardware
launchpad-userguide.pdf
Includes such information as default clock frequencies, which is needed to convert from timer clocks to seconds.
-
See the section: Hardware -> Clocking
%% comments in both md and adoc %%
4.5. Servo power supply
When accelerating the servo’s motor from rest, the servo can draw 700+mA.
-
The AD2’s built-in variable power supply output can only supply about 150mA before current limiting. The servo will fail to even start moving.
-
Supplying +5V to the AUX power input of the AD2 increases the current limit to around 700mA.
-
This is still not quite enough current for robust operation, but works OK if the power supply is around 3.3V. The motor draws too much current at 5V and will cause a safety reset of the AD2 hardware when the servo attempts to move.
-
Plugs and cables are due to arrive Thurs or Fri for this connector.
-
It is always possible to supply power to the servo using a bench power supply (the higher current +6V output, set to 3.3V or 5V). Be sure to connect the COM of the power supply to the GND of your LaunchPad and servo.
The +5V labeled pins on the LaunchPad directly connect to the USB power pins.
You can trace this using LaunchPad schematic from nodes EZFET_VBUS
connected to the USB +5V and jumpered to the target’s +5V
node.
-
At least in-office testing has shown that the +5V pin on the LaunchPad will work for powering the servo. YMMV
-
The 3.3V pin does not work. The DC-DC buck converter cannot supply enough current.
4.6. Code template
Use this example code as a starting point for your code.
Search for the ???
for values you need to fill in and read the comments, this code will not compile or run as-is!
/*
* original file:
* msp430fr69xx_ta0_17.c
*/
#include <msp430.h>
/*
* define these integers as long int: 1234L
* \--------------^
* or they will not be computed correctly!
*/
#define SMCLOCK_HZ ???L // Hz
#define SERVO_PERIOD_HZ 50 // 20ms or 50Hz
#define SERVO_MIN_PERIOD_US 1000L
#define SERVO_MID_PULSE_US 1500L
#define SERVO_MAX_PULSE_US 2000L
// convert to timer clock cycles
#define SERVO_PERIOD (SMCLOCK_HZ / SERVO_PERIOD_HZ)
#define SERVO_MIN_PULSE (SERVO_MIN_PULSE_US * (SMCLOCK_HZ / 1000000L))
#define SERVO_MID_PULSE (SERVO_MID_PULSE_US * (SMCLOCK_HZ / 1000000L))
#define SERVO_MAX_PULSE (SERVO_MAX_PULSE_US * (SMCLOCK_HZ / 1000000L))
int main(void)
{
// Stop WDT
WDTCTL = WDTPW | WDTHOLD;
// Configure GPIO
P1DIR |= BIT0; // P1.0 is LED1 output
// setup P1.6 with TA0CCR1 output signal
// ft6989 datasheet section 6.11.24.4, Table 6-21
// registers P1DIR, P1SEL1, P1SEL0
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
/* Clock setup
*
* none, we are using the LaunchPad default setup, which is
* MCLK = ??? MHz
* SMCLK = ??? MHz
*/
// Configure Timer0_A
TA0CCR0 = SERVO_PERIOD; // PWM Period
TA0CCTL1 = ???; // CCR1 reset/set
TA0CCR1 = SERVO_MID_PULSE; // initial CCR1 PWM duty cycle
// Configure TimerA0 mode and GO
TA0CTL = TASSEL__SMCLK | MC__UP | TACLR; // SMCLK, up mode, clear TAR
// enter LPM3 mode just to demonstrate that the
// output pin is still toggling without help from the CPU
// REPLACE with your application code (reading inputs?)
__bis_SR_register(LPM3_bits);
__no_operation(); // For debugger
}