top of page

MAE144 - Embedded Control & Robotics​

As a student taking MAE144, it is your responsibility to read the course collaboration policy and other FAQs for this course here.

The course texts for MAE144 are available here and here and here.

Click the following links for the midterm (given 7pm Oct 31st), the final (given 7pm Dec 7) and the final solutions. ​​

For the build instructions for the MIP, please click here.


HW7, Final project (due Sat, Dec 10, 11:59pm): HW7 is available in PDF form here.


HW6, Complementary Filtering (due Fri, Dec 2, 11:59pm):  As for HW5, please create a single PDF document containing the answers to all questions and requested plots in this assignment, including your source code on the last page. As you did for HW5, you will email (just once!) a single PDF file (nothing else!) to, with your full name and student ID on the subject line, before the due date/time.  You may work together with a partner and may even share a BeagleBone. However, all source code, answers, and figures must be your own. Copying another’s work is not allowed.

Setup: Make a copy of the program you wrote in the previous assignment “Reading Sensor Data” and rename it to complementary_filter. Then read the RoboticsCape API documentation for discrete filters and ring buffers here and here.


Part 1:  Now you will combine the accelerometer and gyroscope derived angle estimates to make one which has the best qualities of both. In Matlab, design two first order continuous-time filters, one high pass and one low pass. Choose a rise time for your two filters and justify your choice. Make sure that the sum of the two transfer functions is 1. Plot the two filters and their sum on a single bode plot. Make sure to include a legend that clearly identifies what curve is.

Part 2:  Modify your existing sensor reading program to use 100hz for a smoother angle estimate.  Use the discrete filter API to create a low and high pass filter with the same rise time as you used in question 1. Run the accelerometer angle estimate through the low pass filter and the gyroscope angle estimate through the high pass filter. Plot these two filtered values and their sum as you tilt the BeagleBone through the same motion you used in HW5.


Part 3:  Now experiment with the rise time until you find a value you are satisfied with. What is the new rise time you prefer?  Why?

Part 4:  Modify your Matlab code to have continuous time filters with your preferred rise time. Use Tustin’s approximation to generate discrete-time filter constants for a sample rate of 100hz. Now implement these discrete filters WITHOUT using the discrete filter API. When it performs the same as the discrete filter library results, plot again the filtered accelerometer angle, filtered gyroscope angle, and the sum through the same tilting sequence. 

Part 5: (extra credit) Use the ring buffer API to implement your discrete filter. Explain why this is useful, especially for high-order filters.

Part 6:  Exercise 19.11 in NR.  The youtube videos linked above, on the Diophantine Eqn and on Pole Placement for Problematical Systems, should be helpful.


HW5, Reading Sensor Data (due Wed, Nov 23, 5pm):  For this assignment, you will need a BeagleBone Black and a Robotics Cape. You are to have already completed HW4 (below).  Please create a single PDF document containing the answers to all of the questions in this assignment, including your source code on the last page.  For this assignment, you will email (just once!) a single PDF file (nothing else!) to, with your full name and student ID on the subject line, before the due date/time.  You may work together with a partner and may even share a BeagleBone. However, all source code, answers, and figures must be your own. Copying another’s work is not allowed.

Setup: SSH into your BeagleBone Black with the Robotics Cape attached. Run the test_imu example from the command line to confirm the IMU is working. Then, run the calibrate_gyro and calibrate_mag programs so you are calibrated for the remainder of this exercise. Read thoroughly the API documentation for the IMU here.

Part 1: Note the X, Y, and Z axis directions printed on the Robotics Cape which indicate the IMU’s coordinate system. Rotate the BeagleBone about each of these axis and observe the gyro measurements while running the test_imu program. Do these measurements adhere to the right-hand rule?  What are the units of the gyroscope and accelerometer readings displayed with the test_imu program? Now run test_imu with the “-r” command line option to print raw ADC readings. Referencing the API documentation, what are the available full scale ranges of the gyroscope and accelerometer?  For the default full scale ranges used by test_imu, calculate the conversion factors from raw ADC to m/s^2 and deg/s for the accelerometer and gyroscope respectively. 

Part 2:  Using the project template from the Robotics Cape Github page to make a new project for this assignment. Rename the template my_read_sensors. Using the API documentation, write a simple program that uses the DMP mode to print the accelerometer data to the console at 10hz. You may use the test_imu and test_dmp example programs for reference; however all you need is described in the API documentation.
    Note that the math.h library in already included in useful_includes.h and contains the atan2 function documented here.  Modify your program to print an angle in radians of the BeagleBone relative to the direction of gravity about its X axis. It should read close to 0 radians when the Y axis points up, and close to -pi/2 radians while sitting flat on a table with the Z axis pointing up. Your angle estimate may only use two accelerometer axis.
    Since the gyroscope reads an angular rate, you can integrate the rate in rad/s to get an angle in radians relative to the starting angle. Use the Euler integration method to integrate the X-axis gyroscope to get a second angle estimate.
    Once you are confident that the values are correct, set the IMU sample rate to 20hz. Use Matlab or Octave to plot the two angle estimates as you move the BeagleBone through the various motions listed below. 
    ⁃    Hold upright with the Y-axis pointing up
    ⁃    Lean forward pi/4 rad
    ⁃    Lean backward pi/4 rad
    ⁃    Return to starting position

Part 3:  Describe the pros and cons of both estimates in terms of the frequency domain.


HW4, Hello BeagleBone (not to be turned in or graded):   For this HW, you will need a BeagleBone Black, a Robotics Cape, and a host computer with USB.   First, read the following: getting-started, usb, install, project-template, init-cleanup, flow-state, leds, buttons.

Setup:  Using the above resources, make sure your BeagleBone is flashed to a Debian Jessie image at least as new as 10-26-2016. Then, set up USB networking, SSH, and SFTP clients on your host computer. You should now be able to follow the installation instructions above to install the Robotics Cape package.

Making Your First Program: Follow the project template instructions listed above to make your own first project named my_blink. Here you will write your own version of the ‘blink’ example with your own twist. It must meet the following requirements:
- The pause button must toggle the program state between RUNNING and PAUSED.
- The mode button must change what your program does in some way.
- Both the green and red LEDs must do something different, depending on the mode.
- The main while loop must print something to the console to indicate it is running.
- It must exit the main while loop when ctrl-c is pressed.
- It must sleep at some point in the while loop.
- It must print “Goodbye Cruel World” to the console after the main loop exits and before main() returns.



HW3 (due Mon, Nov 7, at class): Write a concise yet complete solution set for the midterm.  If you skip this hw, your midterm grade will be used for this hw; that is, if you think you can do better on this test if you do it at home, this is your chance to show me. Though this hw is open book, there is absolutely no collaboration allowed on this hw only (in contrast with the other hw in this class). This hw is not a substitute for the exam; however, I will look at the grades from both.


HW2 (due Wed, Oct 26, at class):


A.  Taking G(s)=1/s^2, compute (by hand) the G(z) corresponding to the DAC-G(s)-ADC cascade using equation (18.28) in NR.


B.  Taking D(s)=(s+1)/(s^2+100*s), compute (by hand) a D(z) with similar dynamics using Tustin's approximation with prewarping, with the frequency of particular interest taken as omega=10.


C.  Draw a circuit containing a BeagleBone Black, an LED, and a resistor in order to illuminate the LED when a GPIO pin is configured as an output and set to the HIGH state (output Vcc). What is the logic level voltage outputted by the BeagleBone? Refer to the this product page to find the forward voltage bias of a typical surface-mount green LED.  Calculate the required resistance of a series current limiting resistor to ensure that no more than 3ma is pulled from the GPIO pin.

D.  Using the fact that the forward voltage bias of these LEDs is less than Vcc/2 (a voltage which is assumed to be available on your board), draw a second circuit with two LEDs and one resistor such that both LEDs are turned off by putting the GPIO pin into a high-impedance state, and either LED can be turned on when the GPIO pin is set to HIGH or LOW.


E.  Given the encoder wheel shown below, draw the square waveforms you would expect to come out of sensors A and B through one full counterclockwise rotation of the wheel. Assume the sensor reads HIGH (Vcc) when the sensor is in a white region. Start your waveform at time zero as the wheel is currently positioned. What is the resolution of this encoder?​​​​​​

F.  Imagine you are programming a microprocessor tasked with counting the above encoder. It is configured to wake up on a hardware GPIO interrupt every time a signal transitions from one state to another, called "edge-detection". It is also configured to execute one of the following two "Interrupt Service Routines" (ISRs) each time an edge is detected. Fill in your own pseudo-code that increments the global variable ‘position’ up or down depending upon the direction of rotation. You may call the made-up functions ‘get_pin(A)’ and ‘get_pin(B)’ which will return HIGH or LOW (1 or 0) reflecting the state of the pins immediately after the interrupt.

     #define HIGH 1

     #define LOW 0

     int position;

     void pin_A_ISR(){

     // Interrupt Service Routine for Pin A


     void pin_B_ISR(){

     // Interrupt Service Routine for Pin B


This is most easily done with if/then/else logic.  Extra credit if each ISR contains just a single line of C code with no if statements.


HW1 (due Wed, Oct 12, at class):   Exercises 18.7, 18.11, and 18.12 of NR.  Click here for a nice HW1 solution.

bottom of page