ECE 4760: Laboratory 4
One DOF helicopter
You will build a one degree-of-freedom hovering device which allows the user to select the hover angle then controls the lift-motor with user-selectable parameters to maintain constant angle as the load changes. The motor output signal and actual angle will be displayed as waveforms on the oscilloscope. You will use ProtoThreads and write your program as tasks, the the control loop will need to run in an ISR. A video of a prototype is running here, and with waveform output, and stepping angles with tuned PID.
A 2017 solution video of the system built by Kristen Marie Vilcans and Ramita Pinsuwannakub.
- As in lab 2, the SPI DAC you will use is the MCP4822.
Use the DAC and keypad examples shown on the Dev board page.
- Possible pin assignments for TFT-LCD, DAC, ADC and control buttons.
- TFT SPI channel 1 uses
pins 4,5,6, 22 and 25 (RB0, RB1, RB2, MOSI1, SCLK1)
SCK1: connected to RB14 on the PIC
MOSI (SDO1): PPS output group 2 connected to RB11 on the PIC
CS: connected to RB1 on the PIC
SDCS: left unconnected as I'm not using the microSD card for this
RST: connected to RB2 on the PIC
D/C: connected to RB0 on the PIC
VIN: connected to 3.3V supply
GND: connected to gnd
- DAC SPI channel 2 uses pins 11, 14, 26
SDO2 (MOSI) is in PPS output group 2, could be connected to RB5 which is
pin 14, but remember to set
#pragma config JTAGEN = OFF, DEBUG = OFF
CS (chip select) connected to RB4,
pin 11, but remember to set
#pragma config JTAGEN = OFF, DEBUG = OFF
- Two ADC channels (one for angle sensor, one for parameter setting)
Keep the ADC input lines as far as possible from the SPI control signals.
Perhaps use A5 and A1.
- PWM via output compare unit, perhaps OC1 on RPB7, pin 16
- Two buttons connected to Vdd through 300 ohm resistors,
going to RA2 and RA3 with pulldown resistors turned on. pins 9, 10
(for pulldown information, see Keypad section of
For this assignment you must write your code using ProtoThreads 1_2_1.
I suggest the following thread layout, but you can use anything that works for you:
- Thread 1 takes user input and set up PID parameters and the desired angle.
- A timer ISR running at 1 KHz:
-- Reads the ADC to get the actual beam angle.
runs the PID control loop as fast as possible (at least 1000/sec) using the angle measurements
from a potentiometer
-- sets a hardware PWM signal using output-compare unit to control the motor. (see below)
-- writes to channel A of the SPI DAC with the actual beam angle to be displayed as waveform on the oscilloscope.
-- writes to channel B of the SPI DAC
with the motor control signal to be displayed as waveform on the oscilloscope.
- An output compare unit uses a timer to produce the actual motor control PWM signal in hardware.
- Thread 2 updates the LCD at around 10 times per second.
The angle sensor is a 10K potentiometer which costs over $20! Therefore you will ALWAYS limit current through the potentiometer by connecting a resistor in series with the wiper (pin 2), as shown below! The MCP6242 opamp acts as a unity-gain buffer for the anti-aliasing low-pass filter. You will pick C to be the appropriate low-pass filter for the sample rate you choose. You will connect the output of the opamp to one of the ADC channels on the PIC32.
You will need to control the lift-motor from the mcu. DC motors can cause
nasty inductive spikes to wipe out the transistors in the mcu port. The
circuit shown below is fairly safe. An optoisolator completely isolates
the MCU from the motor. The diode placed across the motor shorts out spikes
when the motor is turned off on every PWM pulse. The resistor grounding the base of the phototransistor
should be set for best falltime, probably around 1Mohm. The motor capacitor
should start around 0.1uf. Increase it if there is too much spike noise on
the analog input, but be sure to use ceramic capacitors, not electrolytic.
Electrolytic capacitors are too slow. The pinout of the 4N35 optoisolator
and 2SK4017 are also shown. Note that the bandwidth
of the 4N35 is very small, so use a low PWM frequency, perhaps about 1000
Pin 1 on the 4N35 is marked with a "Y".
Building/simulating the 1-DOF sensor/beam/motor
You will construct the hovering device, similar the the images below.
Remember that your group gets ONE sensor potentiometer to use, so be careful.
Estimate the natural period and damping coefficient of the beam/motor/sensor that you built. You need these values for the system modeling and tuning. The natural period is approximately the simple pendulum natural period. T=2⋅π⋅√(L/g). Where L is the distance from the pivot to the motor, and g is gravitational acceleration. Using the DAC output to the scope, you can estimate the natural period. Also count the number of full cycles that the actual beam makes before it stops, and adjust the damping coefficient in the matlab code (DD) until the undriven pendulum matches the number of cycles. There are two versions of the matlab code. The first is a simulator using radian measure (with some guesses about motor thrust scaling). The second simulator uses angles measured in ADC units and motor control in PWM units, as shown below. The red line is the target angle.
The ADC will probably be set up to measure the 10Kohm servo potentionmeter from zero volts to Vref, resulting in ADC units of 0 to 1023 representing the resistance range of 0 to 10kohm. According to the potientiometer datasheet, the 10K resistance range occurs over 340 degrees of rotation. The useful range of angles for this lab will be 180 degrees (hanging down to vertical above pivot point). The resistance range you can use is therefore 180/340*10Kohm=5.29Kohm, so the raw ADC range will be about 5.29/10*1024=542 counts for 180 degrees rotation. If we set up the potentiometer to read about 520 ADC counts when the beam is hovering at horizontal position, then when hanging straight down the resistance will be about 520-271=249, and when directly over the pivot point about 790.
Building the 1-DOF device:
- Hot glue a motor to one end of the wooden beam.
NOTE: Orient the motor shaft to be at right-angles to the rotation shaft of the knob.
- Roughen the knob surface using sandpaper. Be sure to remove the plastic film.
- Hot glue the other end of the wooden beam to the knob surface.
- Solder a pair of wires (from ribbon cable) to the motor and tape them to the beam.
NOTE: Use only stranded wire peeled off from ribbon cable
The wires themselves can add weight and torque to the beam. Route them close to the
potentiometer shaft to minimize torque.
- Screw the potentiometer bracket to a chunk of wood big enough that you can use a book to weight it down.
Use #4 wood screws, as shown in this image.
- The potentiometer mounting hole on the bracket is slightly too small for the potentiomenter sleeve. You will need to
use the rat-tail (round) file to enlarge the hole.
- When attaching the potentiometer to the mounting bracket be sure the the locating pin (see data sheet) is in the appropriate sheet metal slot. The shaft on these potentionmeters is freely rotating. Therefore, when attaching the beam to the potentiometer shaft you need to check the whole range of shaft motion for continuous resistance. I suggest adjusting the pot to 1/2 full resistance, then attach the knob to the potientiometer shaft with the wooden beam held in the horizontal position. Be sure to use pliers to tighten the potentiometer.
- Solder three wires (from ribbon cable) to the potentiometer.
- Figure out how to put a rotation-stop on the beam so that the beam cannot go past vertical.
I suggest a piece of wire, or a coffee stir-stick or a drinking straw.
The DAC A/B channels will display beam angle and motor control on the scope. This will be useful for debugging and is required for the demo and the writeup. The top trace is the actual angle. You will note that the PID algorithm is poorly tuned in this image. There is an initial jump when the PIC32 is turned on with the beam hanging straight down, followed by oscillating convergence to the horizontal position. The bottom trace is the motor control signal used to drive the PWM. If you use a very large derivitive term in the PID controller to stabilize the oscillations, you may need to lowpass filter the motor signal to display on the scope. I used a first order IIR, digital lowpass, with a time constant of about 16 PWM samples, given by:
motor_disp = motor_disp + ((pwm_on_time - motor_disp)>>4);
Write tasks using ProtoThreads, plus an ISR, and construct a circuit which will:
- Measure the angle of the beam supporting the lift-motor.
- Format the angle and display appropriate messages on an LCD.
- Note that you will need to read two channels of the ADC to read sensor postion and potentiometer.
- Take commands from one potentiometer and buttons:
- Set the desired beam angle.
- Set the PID proportional gain.
- Set the PID differential gain.
- Set the PID integral gain.
- One example of a way to enter values:
- Button 1 puts a selection cyclically onto one of the 4 parameters displayed on the LCD dispay.
Pressing button 1 also freezes the parameter values used in computation.
- Turning the potentiometer changes the value of the parameter.
- Button 1 may be used with the potentiometer to change another parameter.
- Button 2 loads the new parameters for use in computation.
- Use a PID algorithm to control the speed of the motor by producing a PWM drive to the optoisolator. PWM setup example.
- Tune the PID algorithm so that you can change the angle of the beam quickly
and accurately without excessive angle oscillations.
One set of coefficients should produce stable behavior over a range of desired hover angles.
- The user should be able to
enter a desired hover angle and the motor should quickly change the beam to the new angle.
The initial angle of the beam should be around -1.57 radian (hanging straight down).
- Display the motor control value (not the raw PWM signal) on the scope using channel B of the DAC.
- Display the actual beam angle, from the angle sensor, on the scope using channel A of the DAC.
- During the demo, when the system is reset, the beam should go through a quick sequence of defined angle changes:
- At time=0, when holding the reset button, the beam should be hanging vertically.
- At time=0, target angle should be set to horizontal.
- At time=5 seconds, target angle should be set to approximately 30 degrees above horizontal.
- At time=10 seconds, target angle should be set to approximately 30 degrees below horizontal.
- At time=15 seconds, target angle should be set to horizontal.
You will demo all the features above to your TA.
Your program should not need to be
reset during the demo.
Your written lab report should include the sections mentioned in the policy page, and :
- A schematic of the circuit you built.
- Scope screen dumps of typical two-trace: (1) motor-control and (2) actual angle.
Include the demo sequence of four angles.
- A summary of the accuracy of your measurements.
How accurately can you measure the angle?
- How you selected the three PID gains.
- What are the maximum/minimum angles that produce stable behavior for your PID gains?
- What are the settling times at different angles.
- A heavily commented listing of your code.
Copyright Cornell University
November 27, 2017