Option 1 (height sensing and control), or |
Option 2 (mission sequencing) |
Option 1Each test station is equipped with a Devantech sonar sensor unit and a compass. Each sonar unit is equipped with a sonic transmitter which will emit a small burst of clicks. The receiver will sense the signal that has reflected off of some surface. By measuring the return time of the signal, we can infer the distance to the surface.For the heli stations, the sensors will be placed underneath the helicopter (facing upwards). This way, we can measure the height of the heli at a given time. We will then use this information to hover the heli at some specified height. The interface to the sonar unit is as follows:
Note: After the reflected signal has been detected, you must wait for at least 10 msec to command the next sonic pulse. Hint: consider using a counter that tells the ISR "what time it is" (e.g., when to emit the burst, when it is measuring the pulse, and when it is waiting before it emits the next pulse). |
Project Overview: Option 1For this project, you will modify your microcontroller circuit to provide an interface to the sonar unit. In addition, you will be writing the software that is necessary to control the sonar and interpret the signals that you receive from it.Note: in the next project, you will be integrating the current work into the helicopter control problem (and doing height and yaw control simultaneously). So: do not completely dismantle your project 2 implementation. In brief, your code must:
Project ComponentsAll components are required to receive full credit for the project.Part 1: Microcontroller CircuitDesignate one additional input pin and one output pin. Wire these into the sonar connector.Part 2: Sensing DistanceImplement an interrupt service routine (e.g., one that is attached to the timer0 overflow interrupt) that does the following:
Part 3: Height Display
Part 4: Height ControlGiven a height goal, alter the throttle command until the current height matches the height goal.Because your throttle command is not an acceleration (due to the dangling wire), an appropriate implementation is to use an integration controller. Your main loop will look something like this:
void main_loop(void) { float throttle_command = 60.0; while(1) { heading_last = heading_current; heading_current = get_heading(); heading_error = compute_error(heading_current, heading_goal); heading_derivative = compute_derivative(heading_current, heading_last); height_current = get_height(); if(#COMMAND INPUT LINE#) { display_orient(heading_current); }else{ display_orient(heading_error); } display_derivative(heading_derivative); yaw_command = yaw_center + Kp * heading_error - Kv * heading_derivative; set_yaw(yaw_command); throttle_command += Ki * (height_goal - height_current); #Insert code to ensure that throttle_command remains in the valid limits# set_throttle((uint8_t) throttle_command); delay_ms(100); } } |
Project Overview: Option 2For this project, you will modify your microcontroller circuit to extend your external command interface (right now, you have 1 switch to control the orientation display). We will use this command interface to trigger a sequence of height and orientation subgoals.In brief, your code must:
Project ComponentsPart 1: Microcontroller Circuit
Part 2: Finite State MachineImplement in software the following finite state machine:
Note: Develop and test FSM before you move on to the next part (you will have to fake the orientation and throttle goal events)
Part 3: Finite State Machines for ControlControl the craft using this FSM.Here is a starting point for your main loop: void main_loop(void) { int16_t heading_target = get_heading(); int16_t heading_goal = heading_target; float throttle_target = 50.0; // Throttle off float throttle_goal = throttle_target; while(1) { // Finite state machine control switch(state) { case STATE_WAIT: : : break; case STATE_LAND: : : break; : : } // Move the throttle goal a little closer to the target throttle_goal += K_throttle * clip(throttle_target - throttle_goal, max_throttle_step); // Move the heading goal a little closer to the target diff = heading_target - heading_goal; if(diff > 1800) diff -= 3600; if(diff < -1799) diff += 3600; heading_goal += K_heading * clip(diff, max_heading_step); // Get current heading and compute PID control signals heading_last = heading_current; heading_current = get_heading(); heading_error = compute_error(heading_current, heading_goal); heading_derivative = compute_derivative(heading_current, heading_last); if(#COMMAND INPUT LINE#) { display_orient(heading_current); }else{ display_orient(heading_error); } display_derivative(heading_derivative); yaw_command = yaw_center + Kp * heading_error - Kv * heading_derivative; set_yaw(yaw_command); set_throttle((uint8_t) throttle_goal); delay_ms(100); } } /* int16_t clip(int16_t error, int16_t max_error) Clip the error to a value that is between -max_error and max_error */ int16_t clip(int16_t error, int16_t max_error) { if(error > max_error) return(max_error) if(error < -max_error) return(-max_error) return(error); } |
Grades for individuals will be based on the group grade, but weighted by the assessed contributions of the group members.
Last modified: Tue Apr 15 09:58:57 2008